错误“ lambda不是从'std :: function'派生的

时间:2019-04-14 13:47:20

标签: c++ function templates lambda

我正在尝试将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);
}

我遇到以下错误:

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);
                               ^

1 个答案:

答案 0 :(得分:3)

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

let res = map sqr ( filter test [0..10] )
   where
   sqr y = y^2
   test x = (mod x 2==0 && x/=0)

在这种情况下,该包将包含std::function<void(int, double, char)> fce3 ; TestFunction<int, double>(fce3); ,因为char是从function参数推导出的。现在,由于推论还没有结束,并且lambda并不是std :: function,因此替换失败。

要执行此操作,您需要让演绎过程知道结束,在给定参数之前,必须先实例化函数 now 。一种方法是获取函数的地址,例如:

int, double, char

auto pfunc = TestFunction<int, double>;
pfunc(fce);

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