Lamba类型不是由模板化函数或auto关键字推导出来的

时间:2017-01-14 15:35:20

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

我很难理解这一点。我知道我的编译器(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
}

我真的不明白,任何帮助都会很棒。当我将鼠标悬停在变量&#34; p&#34;它将其类型显示为int()。我能做到这一点的唯一方法是明确声明一个像:

这样的指针
int (*ptr) (void) = [] () { return 6;};

我不断得到的错误是:

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

感谢。

3 个答案:

答案 0 :(得分:3)

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

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

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

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

此代码生成的对象类型:

[] () { return 6;}

是一个名字难以辨认的课程(我们称之为“Ftoompsk”以纪念年轻人)

这个:T (*funcPtr)(void)是一个非常易于理解的对象 - 它是一个指向函数的指针,它接受一个void并返回一个T.

因为“Ftoompsk”不捕获任何变量,所以它可能会转换为函数指针。但是,在模板参数推断期间不会进行此转换。

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

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

因为一元加号会在参数推断之前导致转换。然而,这是一个可怕的黑客攻击,当你修改lambda以捕获参数时,它将失败。

采取Kerrek的建议。重构templatedFunc,如图所示。