何时在 lambda 上使用函子

2021-12-23 00:00:00 lambda c++ c++11 functor

是否存在创建函子比使用 lambda 更有意义的情况?

Is there ever a situation where it makes more sense to create a functor than to use a lambda?

我知道我的问题实际上是 何时在函子上使用 lambda,但我想不出在实践中函子会首选而不是 lambda 的情况.对此有什么想法吗?

I know my question is effectively the reverse of when to use a lambda over a functor, but I can't think of a situation in practice where a functor would be preferred over a lambda. Any thoughts on this?

推荐答案

lambda 是一个函子 - 只是用更短的语法定义.

A lambda is a functor - just defined with a shorter syntax.

问题是这种语法是有限的.它并不总是允许您以最有效和最灵活的方式解决问题 - 或者根本不解决.在 C++14 之前,operator() 甚至不能成为模板.

The problem is that this syntax is limited. It doesn't always allow you to solve a problem in the most efficient and flexible way - or at all. Until C++14, the operator() couldn't even be a template.

此外,一个 lambda 表达式只有一个 operator().你不能提供几个重载来区分参数的类型:

Furthermore, a lambda has exactly one operator(). You can't provide several overloads to distinguish between, say, the types of the arguments:

struct MyComparator
{
    bool operator()( int a, int b ) const {return a < b;}
    bool operator()( float a, float b ) const {return /*Some maths here*/;}
};

.. 或对象参数的值类别(即被调用的闭包对象).你也不能定义特殊的成员函数,包括构造函数和析构函数――如果一个函子负责资源怎么办?

.. or value category of the object argument (that is, the closure object that is called). You can also not define special member functions, including constructors and destructors - what if a functor shall be responsible for resources?

lambda 的另一个问题是它们不能递归.当然,普通函数(包括运算符函数)都可以.

Another problem with lambdas is that they cannot be recursive. Of course, normal functions (including operator functions) can be.

还要考虑将 lambda 用作关联容器的比较器或智能指针的删除器是不方便的:您不能直接将闭包类型作为模板参数传递,并且需要从另一个闭包对象构造容器成员.(闭包类型没有默认构造函数!).对于一个不太麻烦的块范围 map:

Also consider that lambdas are unhandy to use as comparators for associative containers or deleters for smart pointers: You can't directly pass the closure type as a template argument and need to construct the containers member from another closure object. (Closure types don't have a default constructor!). For a block-scope map that isn't too much of a hassle:

auto l = [val] (int a, int b) {return val*a < b;};
std::map<int, int, decltype(l)> map(l);

现在,如果您的map 是数据成员,会发生什么?什么模板参数,构造函数初始化列表中的什么初始化器?您必须使用另一个静态数据成员 - 但因为您必须在类定义之外定义它,这可以说是丑陋的.

Now, what happens if your map is a data member? What template argument, what initializer in the constructors initialization list? You'd have to use another static data member - but since you have to define it outside the classes definition that is arguably ugly.

总结:Lambda 对于更复杂的场景没有用处,因为它们不是为这些场景设计的.它们提供了一种简短而简洁的方式来为相应的简单情况创建简单函数对象.

To sum up: Lambdas aren't useful for more complex scenarios because they weren't made for them. They provide a short and concise way of creating simple function objects for correspondingly simple situations.

相关文章