通用 lambda 与标准模板函数(使用什么以及何时使用)

Generic lambdas Vs Standard template functions (What to use and When)

本文关键字:什么 何时使 lambda 标准 函数 通用      更新时间:2023-10-16

通用 Lambda 是一种定义 lambda 的方法,如下所示:

auto identity = [](auto a){return a;}

将此与以下内容进行比较:

template <typename T>
T Identity(T t){return t;}

或与

template <typename T> 
struct Identity { T operator()(T a) { return a; } };

这是我的理解

  1. lambda 允许使用 [&]、[=] 等进行上下文捕获,我不确定这将如何在通用 lambda 中使用/应用。这是主要区别吗?

  2. 通用 lambda 可以强制转换为函数指针,而模板专用化可以强制转换为函数指针。

一个简单的真实示例将有助于了解使用什么以及何时使用。

[附] 这是通用的 lambda 提案: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3559.pdf

与lambdas非常相似,泛型lambdas是通过等效于隐式定义的函数对象来定义的(其中非泛型lambda具有额外的能力,即通过空捕获它们可以转换为函数指针)。泛型和非泛型 lambda 之间唯一真正的区别是泛型 lambda 具有调用运算符,它是一个函数模板,而它是非泛型 lambda 的非模板。

    对于通用 lambda,不存在
  1. 到函数指针的转换(参见 5.1.2 [expr.prim.lambda] 第 6 段)。
  2. 由于泛型 lambda 仍然是具有调用运算符的对象,因此可以直接用作可以使用泛型函数对象的参数。函数模板的情况并非如此:它们的行为更像是一个重载集,您需要先实例化它们,然后才能将它们作为函数对象传递。
  3. 虽然无法获取指向函数模板的指针
  4. ,但可以获取指向函数模板专用化的指针(如注释中@Columbo指出的那样,函数模板专用化是一个函数)。您无法从通用 lambda 中获取指向函数的指针。
  5. 函数模板参与重载解析,而函数对象
  6. 并不真正参与:在名称查找期间找到对象时,即使可以找到具有相同名称且与重载匹配良好的函数,也会选择此对象。这意味着,这两者并不等同:

    template <typename T>
    auto identity(T value) { return value; }
    auto identity = [](auto value) { return value; }
    

    第二个实现劫持名称,而前者用作重载解析中的候选者。

除了从函数内部创建的辅助对象之外,我会对不打算作为自定义点的函数使用通用 lambda(例如,如果标准库算法是这样的对象会很好)。主要好处是函数对象可以很容易地适应,例如,使用std::bind()而函数模板则不然。