我们有一个函数将函数对象作为参数。函数有两个重载,函数签名不同。
#include <functional>
template <typename T>
void foo(std::function<void(T)> bar)
{
}
template <typename T>
void foo(std::function<void(int, T)> bar)
{
}
int main()
{
foo([](float number) {
});
return 0;
}
但是,此代码无法编译。
error C2784: 'void foo(std::function<void(int,T)>)' : could not deduce template argument for 'std::function<void(int,T)>' from 'main::<lambda_2b4e4413ec419a4ac179a0b64ebde221>' : see declaration of 'foo'
error C2784: 'void foo(std::function<void(T)>)' : could not deduce template argument for 'std::function<void(T)>' from 'main::<lambda_2b4e4413ec419a4ac179a0b64ebde221>' : see declaration of 'foo'
我认为模板本身和重载都存在问题。如何提供两个与上述签名匹配的功能?
答案 0 :(得分:3)
C ++中的Lambdas是专门为每个lambda对象创建的匿名类的实例,这意味着具有相同代码的两个lambda实际上是不同的对象。
这也意味着你不能在不使用模板的情况下传递lambda,因为没有lambda类型。 Lambda既不是std::function
(也不是从它派生的),也不是函数指针。它们是实现应用程序运算符的唯一类型,即operator()
。
您可以使用static_cast operator
来完成template <typename T>
void foo(std::function<void(T)> bar)
{
}
foo( static_cast< std::function<void(float)> >( [](float number){}));
//or
foo( std::function<void(float)>{ [](float){} } );
答案 1 :(得分:1)
原因显然是让每个lambda表达式都有自己的类型的副作用之一。
这意味着您无法声明lambda参数或指向lambda的指针。这也意味着在需要类型推导时不能使用lambdas(例如,用于模板实例化)。
解决方案是尽快将lambda包装到std::function<...>
个对象中,因为它们具有可以在模板中指定和匹配的类型。
例如,你不能拥有一个返回lambda的函数,或者在一个成员中存储一个lambda ......但是你可以向成员返回std::function
或存储std::function
。
具体来说,您的代码与
一起使用foo(std::function<void(float)>([](float number){});