问题描述
我有以下模板化函数(编译器中启用了 C++ 最新标准 - 但也许 17 个就足够了).
#include 模板void MyFunction(const std::function& 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'的声明
我的目标是python 风格的装饰器".所以基本上是这样的:
templateauto MyFunction(std::function&& callback) ->std::function{return [callback = std::move(callback)](TArgs...args)->TReturn{返回回调(std::forward(args)...);};}
如果我使用模板而不是 std::function,我将如何推导出参数包和返回值?有没有办法通过一些可调用特征"从可调用对象中获取它?
是的.模板参数推导不会考虑隐式转换.>
类型推导不考虑隐式转换(上面列出的类型调整除外):这是重载解析的工作,稍后发生.
这意味着给定 MyFunction([](int){});
,隐式转换(从 lambda 到 std::function
)不会被考虑,然后对 TReturn
和 TArgs
的推导失败,调用尝试也失败.
作为解决方法,您可以
- 使用显示的显式转换
正如 评论所建议的那样,只需使用函子的单个模板参数.例如
templateauto MyFunction2(F&&回调){return [callback = std::move(callback)](auto&&... args){return callback(std::forward(args)...);};}
I have the following templated function (C++ latest standard is enabled in the compiler - but maybe 17 would be enough).
#include <functional>
template<typename TReturn, typename ...TArgs>
void MyFunction(const std::function<TReturn(TArgs...)>& callback);
int main()
{
MyFunction(std::function([](int){}));
MyFunction([](int){});
}
The first call compiles, when I explicitly convert it to std::function, but the second case does not.
In the first case the template deduction is done automatically, the compiler only knows that it shall convert it to some std::function and able to deduce the parameter and return type.
However in the second case it shall(?) also know that the lambda shall be converted to some std::function, but still unable to do it.
Is there a solution to get the second one running? Or can it be that for templates the automatic conversion does not take place at all?
The error message is:
What I am aiming for is a "python style decorator". So basically this:
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)...);
};
}
If I used a template instead of std::function, the how would I deduce the parameter pack and return value? Is there some way to get it from a callable via some "callable traits"?
Yes. Implicit conversions won't be considered in template argument deduction.
That means given MyFunction([](int){});
, the implicit conversion (from lambda to std::function
) won't be considered, then the deduction for TReturn
and TArgs
fails and the invocation attempt fails too.
As the workarounds, you can
- Use explicit conversion as you showed
As the comment suggested, just use a single template parameter for functors. e.g.
template<typename F> auto MyFunction2(F&& callback) { return [callback = std::move(callback)](auto&&... args) { return callback(std::forward<decltype(args)>(args)...); }; }
这篇关于从 lambda 构造 std::function 参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!