错误“lambda 不是从‘std::function’派生的”

Lud*_*cka 6 c++ lambda templates function

我正在尝试将 lambda 传递给通过可变参数模板定义的 std::function<> ,但这似乎不适用于 gcc。

有什么原因,为什么此代码在 gcc 7.4.0 上不起作用,但在 Visual Studio 2017 上正常工作?有什么方法可以让它在 gcc 上也能工作,而无需先手动将其转换为 std::function<> ?

#include <functional>

template<class ...TParams>
int TestFunction(std::function<void(TParams...)> )
{
    return 0;
}

void Test()
{
    auto fce = [](int /*n*/, double /*d*/) {};

    //This doesn't work with error no matching function for call to 'TestFunction<int, double>(Test()::<lambda(int, double)>&)'
    TestFunction<int, double>(fce);

    //but this works correctly
    std::function<void(int, double)> fce2 = fce;
    TestFunction<int, double>(fce2);
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

main.cpp: In function 'void Test()':
main.cpp:116:31: error: no matching function for call to 'TestFunction<int, double>(Test()::<lambda(int, double)>&)'
  TestFunction<int, double>(fce);
                               ^
main.cpp:106:5: note: candidate: template<class ... TParams> int TestFunction(std::function<void(TParams ...)>)
 int TestFunction(std::function<void(TParams...)> fceCallback)
     ^~~~~~~~~~~~
main.cpp:106:5: note:   template argument deduction/substitution failed:
main.cpp:116:31: note:   'Test()::<lambda(int, double)>' is not derived from 'std::function<void(TParams ...)>'
  TestFunction<int, double>(fce);
                               ^
Run Code Online (Sandbox Code Playgroud)

Sto*_*ica 5

尾随模板参数包总是留有进一步推论的空间。指定前两个参数不会阻止您执行以下操作:

std::function<void(int, double, char)> fce3 ;
TestFunction<int, double>(fce3);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,包将包含int, double, char,因为字符是从函数参数中推导出来的。现在,因为演绎还没有结束,并且 lambda 不是 std::function,所以替换失败。

为了使这项工作,您需要让推论过程知道它已经结束,现在需要一个实例化的函数,然后再给它一个参数。一种方法是获取函数的地址,例如:

auto pfunc = TestFunction<int, double>;
pfunc(fce);
Run Code Online (Sandbox Code Playgroud)

或者

(&TestFunction<int, double>)(fce);
Run Code Online (Sandbox Code Playgroud)

获取函数模板的地址是另一个可以进行模板参数推导的上下文。在这种情况下,尾随包被推断为空,并且您将获得一个指向您可能调用的函数的指针。

  • 当然,如果有一个额外的函数模板可以接受这些参数,那就太糟糕了。然后必须使用确切的类型来强制转换或分配函数指针。 (2认同)