我很难理解这一点。我知道我的编译器(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
谢谢。
闭包对象(适当类型)具有到函数指针类型的隐式转换,但它本身并不是函数指针。模板参数推导不考虑隐式转换;你拥有的东西的模式与你的函数模板签名不匹配。
第一个代码示例之所以有效,是因为you提前执行了到函数指针的转换。
编写接受可调用函数模板的更好方法是根本不使用函数指针,而是对可调用对象本身进行参数化:
template <typename T> void templatedFunc(T f) { f(); }
您可以使用一元
+
将无状态 lambda 强制转换为函数指针,然后它将与您的函数模板匹配:
templatedFunc(+[] () { return 6; });
此代码生成的对象类型:
[] () { return 6;}
这个班级有一个难以言说的名字(让我们称其为“Ftoompsk”,以纪念年轻人)
this:
T (*funcPtr)(void)
是一个非常可表达的类型的对象 - 它是一个指向接受 void 并返回 T 的函数的指针。
由于“Ftoompsk”不捕获任何变量,因此它可能会转换为函数指针。但是,在模板参数推导过程中不会发生这种转换。
您可以通过以下方式强制转换:
auto p = +[] () { return 6; };
templatedFunc(p);
因为一元加会导致在参数推导之前进行转换。然而,这是一个可怕的 hack,当你修改 lambda 来捕获参数时,它就会失败。
听取 Kerrek 的建议。重构 templatedFunc 如图所示。