1

我们有一个将函数对象作为参数的函数。该函数有两个重载,它们的函数签名不同。

#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'

我认为模板本身和重载都有问题。如何提供与上述签名匹配的两个函数?

4

2 回答 2

3

C++ 中的 Lambda 是专门为每个 lambda 对象创建的匿名类的实例,这意味着具有相同代码的两个 lambda 实际上是不同的对象。

这也意味着你不能在不使用模板的情况下传递 lambda,因为没有 lambda 类型。Lambda 既不是std::function(也不是从它派生的)也不是函数指针。它们是实现应用程序运算符的唯一类型,即operator().

您可以使用 static_cast 运算符来做到这一点

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){} } );
于 2014-09-06T13:47:31.587 回答
1

原因显然是每个 lambda 表达式都有自己的类型的副作用之一。

例如,这意味着您不能声明 lambda 参数或指向 lambda 的指针。这也意味着当需要类型推导时(例如,用于模板实例化),您不能使用 lambda。

解决方案是尽快将 lambdas 包装到std::function<...>对象中,因为它们具有可以在模板中指定和匹配的类型。

例如,您不能有一个返回 lambda 的函数,或将 lambda 存储在成员中......但您可以返回一个std::function或存储std::function到成员中。

在特定情况下,您的代码可以使用

foo(std::function<void(float)>([](float number){});
于 2014-09-06T14:09:05.403 回答