从lambda构造std :: function参数

问题描述 投票:4回答:1

我有以下模板化函数(在编译器中启用了C ++最新标准 - 但也许17就足够了)。

#include <functional>

template<typename TReturn, typename ...TArgs>
void MyFunction(const std::function<TReturn(TArgs...)>& callback);

int main()
{
    MyFunction(std::function([](int){}));
    MyFunction([](int){});
}

当我明确地将它转换为std :: function时,第一个调用编译,但第二个案例没有。

在第一种情况下,模板推导是自动完成的,编译器只知道它应该将它转换为某个std :: function并能够推导出参数和返回类型。

但是在第二种情况下它应该(?)也知道lambda应该被转换为某个std :: function,但是仍然无法做到。

是否有解决方案让第二个运行?或者,对于模板而言,自动转换根本不会发生?

错误消息是:

错误C2672:'MyFunction':找不到匹配的重载函数

错误C2784:'void MyFunction(const std :: function <_Ret(_Types ...)>&)':无法推断'const std :: function <_Ret(_Types ...)>的模板参数

注意:看'MyFunction'的声明

我的目标是“蟒蛇风格装饰”。基本上这个:

template<typename TReturn, typename ...TArgs>
auto MyFunction(std::function<TReturn(TArgs...)>&& callback) -> std::function<TReturn(TArgs...)>
{
     return [callback = std::move(callback)](TArgs... args)->TReturn
     {
          return callback(std::forward<TArgs>(args)...);
    };
}

如果我使用模板而不是std :: function,我将如何推导出参数包并返回值?有没有办法从可调用的一些“可调用的特征”中获取它?

c++ templates lambda stl template-deduction
1个回答
4
投票

或者,对于模板而言,自动转换根本不会发生?

是。在template argument deduction中不会考虑隐式转换。

类型推导不考虑隐式转换(上面列出的类型调整除外):这是重载解析的工作,稍后会发生。

这意味着给定MyFunction([](int){});,将不考虑隐式转换(从lambda到std::function),然后TReturnTArgs的推论失败,并且调用尝试也失败了。

作为解决方法,你可以

  1. 如您所示,使用显式转换
  2. 正如the comment建议的那样,只需使用一个模板参数作为仿函数。例如 template<typename F> auto MyFunction2(F&& callback) { return [callback = std::move(callback)](auto&&... args) { return callback(std::forward<decltype(args)>(args)...); }; }
© www.soinside.com 2019 - 2024. All rights reserved.