我很难理解这一点。我知道我的编译器(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
感谢。
答案 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,如图所示。