Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Generic Lambdas are a way of defining lambdas that read as follows:

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

Compare this with:

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

or with

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

This is my understanding

  1. lambdas allow context capture using [&], [=], etc, I am not sure how this will be used / applied in generic lambdas. Is this the main difference ?

  2. generic lambdas can be cast to function pointers whereas, template specialisation can be cast to function pointers.

A simple real world example will be useful to understand what to use and when.

[Appended] Here is the generic lambda proposal : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3559.pdf

like image 663
Ram Avatar asked Dec 30 '14 19:12

Ram


1 Answers

Pretty much like lambdas, generic lambdas are defined through equivalence to an implicitly defined function object (where non-generic lambdas have the additional ability that with empty capture they can convert to a function pointer). The only real difference between generic and non-generic lambdas is that generic lambda have call operator which is a function template while it is a non-template for non-generic lambdas.

  1. For generic lambdas the conversion to function pointers doesn't exist (see 5.1.2 [expr.prim.lambda] paragraph 6).
  2. Since generic lambdas are still objects with a call operator, they can be used directly as an argument where a generic function objects can be used. That is not the case for a function templates: these behave more like an overload set and you need to get the instantiated before you can pass them as a function object.
  3. Although you can't get a pointer to a function template, you can get a pointer to a function template specialization (as @Columbo pointed out in a comment, a function template specialization is a function). You can't get a pointer to a function out of a generic lambda.
  4. Function templates participate in overload resolution while function objects don't really participate: when an object is found during name look-up this object is chosen even if there could be functions found with the same name and with a nice match for overloading. This implies, that these two are not equivalent:

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

    The second implementation hijacks the name while the former is used as a candidate in overload resolution.

Aside from auxiliary objects created from within a function I would use generic lambdas for functions which are not meant as customization points (e.g. it would be nice if standard library algorithms were such objects). The main benefit is that function objects can be readily adapted, e.g., using std::bind() which is not true for function templates.

like image 51
Dietmar Kühl Avatar answered Nov 15 '22 00:11

Dietmar Kühl