我正在尝试将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);
^
答案 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);
获取功能模板的地址是可以进行模板参数推导的另一个上下文。在这种情况下,尾随包被推导出为空,您将获得一个指向可能要调用的函数的指针。