use*_*723 6 c++ lambda templates stl template-argument-deduction
我有以下模板化函数(编译器中启用了 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){});
}
Run Code Online (Sandbox Code Playgroud)
当我显式将其转换为 std::function 时,第一个调用会编译,但第二种情况不会。
在第一种情况下,模板推导是自动完成的,编译器只知道它将其转换为某个 std::function 并能够推导参数和返回类型。
然而,在第二种情况下,它应该(?)也知道 lambda 应转换为某些 std::function,但仍然无法做到这一点。
有没有办法让第二个运行?或者对于模板来说,自动转换根本不会发生?
错误信息是:
错误 C2672:“MyFunction”:找不到匹配的重载函数
错误 C2784: 'void MyFunction(const std::function<_Ret(_Types...)> &)':无法推导出 'const std::function<_Ret(_Types...)> 的模板参数
注意:请参阅“MyFunction”的声明
我的目标是“Python风格的装饰器”。所以基本上是这样的:
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)...);
};
}
Run Code Online (Sandbox Code Playgroud)
如果我使用模板而不是 std::function,我将如何推导出参数包和返回值?有没有办法通过一些“可调用特征”从可调用对象中获取它?
或者对于模板来说,自动转换根本不会发生?
是的。模板参数推导中不会考虑隐式转换。
类型推导不考虑隐式转换(除了上面列出的类型调整之外):这是重载解析的工作,稍后发生。
这意味着给定,不会考虑MyFunction([](int){});隐式转换(从 lambda 到),然后和 的推导失败,调用尝试也失败。std::functionTReturnTArgs
作为解决方法,您可以
正如评论所建议的,只需对函子使用单个模板参数。例如
template<typename F>
auto MyFunction2(F&& callback)
{
return [callback = std::move(callback)](auto&&... args)
{
return callback(std::forward<decltype(args)>(args)...);
};
}
Run Code Online (Sandbox Code Playgroud)