C++ 从lambda构造std::函数参数
我有以下模板函数(编译器中启用了C++最新标准,但可能17个就足够了)C++ 从lambda构造std::函数参数,c++,templates,lambda,stl,template-argument-deduction,C++,Templates,Lambda,Stl,Template Argument Deduction,我有以下模板函数(编译器中启用了C++最新标准,但可能17个就足够了) #包括 模板 void MyFunction(const std::function和callback); int main() { MyFunction(std::function([](int){})); MyFunction([](int){}); } 当我显式地将第一个调用转换为std::function时,它会编译,但第二个调用不会编译 在第一种情况下,模板推导是自动完成的,编译器只知道它应该将其转换为某个std
#包括
模板
void MyFunction(const std::function和callback);
int main()
{
MyFunction(std::function([](int){}));
MyFunction([](int){});
}
当我显式地将第一个调用转换为std::function时,它会编译,但第二个调用不会编译
在第一种情况下,模板推导是自动完成的,编译器只知道它应该将其转换为某个std::函数,并且能够推导参数和返回类型
然而,在第二种情况下,它也应该(?)知道lambda应该被转换成一些std::function,但仍然无法这样做
有没有办法让第二个运行起来?或者,对于模板,自动转换根本不会发生
错误消息是:
错误C2672:“MyFunction”:未找到匹配的重载函数
错误C2784:“void MyFunction(const std::function&”):无法推断“const std::function”的模板参数
注:参见“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)...);
};
}
模板
自动MyFunction(std::function&&callback)->std::function
{
return[callback=std::move(callback)](targets…args)->TReturn
{
返回回调(std::forward(args)…);
};
}
如果我使用模板而不是std::函数,我将如何推断参数包和返回值?有没有办法通过一些“可调用特性”从一个可调用对象获得它
或者,对于模板,自动转换根本不会发生
对。在中不考虑隐式转换
类型推导不考虑隐式转换(除了上面列出的类型调整):这是超载分辨率的工作,稍后会发生。
这意味着给定的MyFunction([](int){})代码>,隐式转换(从lambda到std::function
)将不被考虑,然后TReturn
和TArgs
的推导将失败,调用尝试也将失败
作为解决办法,您可以
如图所示,使用显式转换
正如建议的那样,只需为函子使用一个模板参数。e、 g
template<typename F>
auto MyFunction2(F&& callback)
{
return [callback = std::move(callback)](auto&&... args)
{
return callback(std::forward<decltype(args)>(args)...);
};
}
模板
自动MyFunction2(F&回调)
{
return[callback=std::move(callback)](auto&&…args)
{
返回回调(std::forward(args)…);
};
}
你会犯什么错误?请编辑您的问题以包含它们(完整的和完整的)。根据用例和设计,您可以通过为可调用对象本身使用单个模板类型来绕过此问题,如模板void MyFunction(F callback)代码>旁注,不要在模板中使用std::函数,将lambda类型设为模板参数,并通过std::is_可调用(相关时)约束它。谢谢大家。请看我更新的问题我将我的问题编辑得更具体一点,我的目标是没有从lambda到std::function
的隐式转换,是吗?但是,存在将非捕获lambda隐式转换为函数指针的过程,而函数指针又可用于初始化std::function
。我弄错了吗?@krzysiekkabowiak std::函数有一个(第五个)函数。@songyuanyao,在我喝完第一杯咖啡之前,我不应该发表评论。我怎么会错过从一个可调用对象(lambda是)构造std::function
,我使用了很多次,而只想到了通过函数指针来构造呢?现在可以了,谢谢。JVAPen建议使用std::is:invocablem检查类型,但使用static_assert(std::is_invocable::value,“包装的对象必须是invocable”);总是给出false,断言就会失败
template<typename F>
auto MyFunction2(F&& callback)
{
return [callback = std::move(callback)](auto&&... args)
{
return callback(std::forward<decltype(args)>(args)...);
};
}