Generic lambdas Vs标准模板函数(使用什么和何时)

时间:2014-12-30 19:47:30

标签: c++ generics c++11 lambda c++14

Generic Lambdas是一种定义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. lambdas允许使用[&amp;],[=]等进行上下文捕获,我不确定如何在通用lambda中使用/应用它。这是主要区别吗?

  2. 泛型lambda可以转换为函数指针,而模板特化可以转换为函数指针。

  3. 一个简单的现实世界示例将有助于了解使用什么以及何时使用。

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

1 个答案:

答案 0 :(得分:6)

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

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

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

    第二个实现劫持了名称,而前者被用作重载决策的候选者。

  5. 除了从函数内创建的辅助对象之外,我将使用通用lambda来表示不是自定义点的函数(例如,如果标准库算法是这样的对象,那将会很好)。主要的好处是可以很容易地调整功能对象,例如,使用std::bind(),这对于功能模板是不正确的。