我具有以下模板化功能(在编译器中启用了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:'无效的MyFunction(const std :: function <_Ret(_Types ...)>&)':无法推断'const std :: function <_Ret(_Types ...)>的模板参数/ p>
注意:请参见“ 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)...);
};
}
如果我使用模板而不是std :: function,我将如何推断参数包和返回值?是否可以通过一些“可调用特征”从可调用对象中获取它?
答案 0 :(得分:4)
对于模板来说,根本就不会自动转换吗?
是的。在template argument deduction中不会考虑隐式转换。
类型推导不考虑隐式转换(上面列出的类型调整除外):这是超载解析的工作,稍后会发生。
这意味着在给定MyFunction([](int){});
的情况下,将不考虑隐式转换(从lambda到std::function
),然后对TReturn
和TArgs
的推论失败,并且调用尝试也失败。
作为解决方法,您可以
根据the comment的建议,仅对函子使用单个模板参数。例如
template<typename F>
auto MyFunction2(F&& callback)
{
return [callback = std::move(callback)](auto&&... args)
{
return callback(std::forward<decltype(args)>(args)...);
};
}