【问题标题】:Lamba type is not being deduced by templated function or auto keyword模板化函数或 auto 关键字未推断出 Lamba 类型
【发布时间】:2017-01-14 15:35:20
【问题描述】:

我很难理解这一点。我知道我的编译器(Visual Studio)知道 lambda 是什么“类型”,因为有时它显示它是一个 lambda,但是我的模板没有推断它,auto 关键字也没有。

template <typename T> void templatedFunc(T (*funcPtr)(void)) { }

int main()
{
    templatedFunc([] () { return 6;} );     // Error, no template matches argument list

    int (*funcPtr)(void) = [] () { return 6;};
    templatedFunc(funcPtr);                 // Works fine

    auto p = [] () { return 6; };
    templatedFunc(p);                       // Error, no template matches

    auto p = [] () -> int { return 6; };    // Trying with explicit return type
    templatedFunc(p)                        // Error, still doesn't work
}

我真的不明白,任何帮助都会很棒。当我将鼠标悬停在变量“p”上时,它的类型显示为 int()。我可以使这项工作的唯一方法是明确声明一个指针,如:

int (*ptr) (void) = [] () { return 6;};

我不断收到的错误是:

No instance of function template matches the argument list. Argument types are lambda []int () -> int

谢谢。

【问题讨论】:

    标签: c++ templates pointers lambda type-deduction


    【解决方案1】:

    闭包对象(适当的类型)有一个隐式转换到函数指针类型,但它本身不是函数指针。模板参数推导不考虑隐式转换;你所拥有的不是与你的函数模板签名匹配的模式。

    第一个代码示例有效,因为正在提前执行到函数指针的转换。

    编写接受可调用的函数模板的更好方法是根本不使用函数指针,而是对可调用对象本身进行参数化:

    template <typename T> void templatedFunc(T f) { f(); }
    

    【讨论】:

    • auto不能推断类型是不是同一个原因?
    • @TitoneMaurice:我不明白。 auto 推导出一个类型。它可能不是你想的那种类型。
    • “auto p =”之后的类型是一个 lambda,我的编译器告诉我它是一个 lambda,我希望 p 是一个指向 lambda 的函数指针,因为它们已转换为函数指针。
    • @TitoneMaurice:他们没有“转换”。它们是可转换的。很大的区别! p 的类型是 lambda 表达式的类型,即闭包类型。
    【解决方案2】:

    您可以使用一元 + 将无状态 lambda 强制转换为函数指针,然后它将匹配您的函数模板:

    templatedFunc(+[] () { return 6; });
    

    【讨论】:

    • templatedFunc(+[] () { return 6; });在 Visual Studio 中对我不起作用。有没有关于加号实际作用的信息?我找不到。
    【解决方案3】:

    这段代码产生的对象类型:

    [] () { return 6;}
    

    是一个名字难以形容的班级(我们称它为“Ftoompsk”以纪念年轻人)

    this:T (*funcPtr)(void) 是一个非常容易表达的对象类型 - 它是一个指向接受 void 并返回 T 的函数的指针。

    因为“Ftoumpsk”不捕获任何变量,它可能会被转换为函数指针。但是,在模板参数推导过程中不会发生这种转换。

    您可以通过以下方式强制转换:

    auto p = +[] () { return 6; };
    templatedFunc(p);
    

    因为一元加号导致在参数扣除之前进行转换。然而,这是一个可怕的 hack,一旦您修改 lambda 以捕获参数,它就会失败。

    听从 Kerrek 的建议。如图所示重构 templatedFunc。

    【讨论】:

    • 自动 p = +[]() { 返回 6; };在 Visual Studio 中对我不起作用。有关于它的作用的任何信息吗?我找不到。
    • @TitoneMaurice 信息在 c++ 标准中。但这个网站也是一个很好的来源:en.cppreference.com/w/cpp/language/lambda。微软并不以对标准的良好遵守而闻名(他们正在逐渐改进)。除非您使用的是 VS2015 或更高版本,否则我不会对良好的标准一致性抱有希望。
    • MSVC 的 lambdas(至少是 32 位)有 四个 转换运算符(每个调用约定一个),因此不能很好地响应一元 +
    猜你喜欢
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    相关资源
    最近更新 更多