是否存在创建仿函数比使用lambda更有意义的情况?
我知道我的问题实际上与when to use a lambda over a functor相反,但我无法想到实际情况,其中一个仿函数是首选的而不是lambda。有什么想法吗?
答案 0 :(得分:40)
lambda是一个仿函数 - 只是用较短的语法定义。
问题在于此语法有限。它并不总能让您以最有效和最灵活的方式解决问题 - 或者根本无法解决问题。在C ++ 14之前,operator()
甚至不能成为模板。
此外,lambda只有一个operator()
。您不能提供几个重载来区分,例如,参数的类型:
struct MyComparator
{
bool operator()( int a, int b ) const {return a < b;}
bool operator()( float a, float b ) const {return /*Some maths here*/;}
};
..或对象参数的值类别(即被调用的闭包对象)。你也可以不定义特殊的成员函数,包括构造函数和析构函数 - 如果函子应该负责资源怎么办?
lambdas的另一个问题是它们不能递归。当然,正常的功能(包括操作员功能)可以是。
还要考虑lambdas不能用作关联容器的比较器或智能指针的删除器:您不能直接将闭包类型作为模板参数传递,并且需要从另一个闭包对象构造容器成员。 (闭包类型没有默认构造函数!)。对于块范围map
而言,这不是一件麻烦事:
auto l = [val] (int a, int b) {return val*a < b;};
std::map<int, int, decltype(l)> map(l);
现在,如果您的map
是数据成员,会发生什么?什么模板参数,构造函数初始化列表中的初始化器是什么?您必须使用另一个静态数据成员 - 但是因为您必须在类定义之外定义它,这可能是丑陋的。
总结:Lambdas对于更复杂的场景没有用,因为它们不适用于它们。它们提供了一种简洁明了的方法,可以在相应的简单情况下创建简单函数对象。
答案 1 :(得分:15)
当我
时,我会考虑在lambda上使用仿函数答案 2 :(得分:7)
我能想到两个案例:
当仿函数携带内部状态时,仿函数存在一个非平凡的生命周期问题。它在用途
当您必须在整个地方使用相同的代码时,从维护的角度来看,在自己的标题中编写并将其保存为仿函数可能是一个好主意
答案 3 :(得分:5)
lambda不能是used in an unevaluated context。一个特别人为的例子是Shafik's回答:
- 醇>
在很多情况下它只是无用,因为每个lambda都有一个独特的类型,假设的例子给出:
template<typename T, typename U> void g(T, U, decltype([](T x, T y) { return x + y; }) func); g(1, 2, [](int x, int y) { return x + y; });
声明和调用中lambda的类型 不同(按照定义),因此无法使用。
因此,即使是具有相同语法的lambda也不能用来代替另一个。在这种情况下,算子将起作用。