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

Posted

技术标签:

【中文标题】错误“lambda 不是从 \'std::function\' 派生的【英文标题】:Error "lambda is not derived from 'std::function'错误“lambda 不是从 'std::function' 派生的 【发布时间】:2019-09-04 15:45:57 【问题描述】:

我正在尝试将 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】:

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

std::function<void(int, double, char)> fce3 ;
TestFunction<int, double>(fce3);

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

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

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

(&TestFunction<int, double>)(fce);

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

【讨论】:

当然,如果有一个额外的函数模板可以接受这些参数,那就太糟糕了。然后必须使用确切的类型强制转换或分配函数指针。 有趣,感谢您的解释。不幸的是 auto pfunc 或 &TestFunction 不是理想的解决方案。 TestFunction 只是测试用例,在我的真实应用程序中,我有一个类(MessageBroker),我想在其中注册不同类型的回调,这些回调能够接收不同数量的参数和类型(MessageBroker.RegisterCallback(msgType,function ). 有没有办法立即实例化函数? @LudekVodicka - 没有什么复杂的浮现在脑海中。但老实说,我认为这只是这个设计要提出的第一个问题。可能值得重新考虑。 我正在考虑通过为一到四个模板参数创建(例如)四个版本的 TestFunction 来解决这个问题。这样,我获得了所需的功能,而不会弄乱动态参数计数。对于我的目的,最多四个参数就足够了。无论如何,谢谢你的解释。 @Yakk 我不确定你的意思。

以上是关于错误“lambda 不是从 'std::function' 派生的的主要内容,如果未能解决你的问题,请参考以下文章

Informix 错误:发生了语法错误。错误代码:-201

我收到一个错误:“MetaMask - RPC 错误:错误:错误:[ethjs-rpc] rpc 错误与有效负载”

错误精灵错误跟踪器错误

网页打开显示错误500是啥意思

PHP错误处理

PHP的错误处理