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

问题描述 投票:0回答:3

我很难理解这一点。我知道我的编译器(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
3个回答
3
投票

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

第一个代码示例之所以有效,是因为you提前执行了到函数指针的转换。

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

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

1
投票

您可以使用一元

+
将无状态 lambda 强制转换为函数指针,然后它将与您的函数模板匹配:

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

1
投票

此代码生成的对象类型:

[] () { return 6;}

这个班级有一个难以言说的名字(让我们称其为“Ftoompsk”,以纪念年轻人)

this:

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

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

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

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

因为一元加会导致在参数推导之前进行转换。然而,这是一个可怕的 hack,当你修改 lambda 来捕获参数时,它就会失败。

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

© www.soinside.com 2019 - 2024. All rights reserved.