Is it safe to assume that identical lambda expressions have different types?

  • A+

I am experimenting with lambdas and the fact that different lambda expressions have different types, even though they are the same. Consider this code

#include <iostream>  template <typename T> void once(T t){     static bool first_call = true;     if (first_call) t();     first_call = false; }  int main() {         int counter = 0;     auto a = [&counter](){counter++;};     once(a);     once(a);     std::cout << counter;              // 1      auto b = a;                        // same type     once(b);     std::cout << counter;              // 1      auto c = [&counter](){counter++;}; // different type     once(c);     once(c);                    std::cout << counter;              // 2 } 

This prints 112, ie a and b are of course of same type and c has a different type.

Is the compiler allowed to let c be of the same type than a?

I mean the expressions are identical and it would be an obvious optimization.

PS: In case the capture prevents such an optimization, then what about lambdas without capture?

related: what is the type signature of a c++11/1y lambda function? and Can the 'type' of a lambda expression be expressed?

Is the compiler allowed to let c be of the same type than a?

No. [&counter](){counter++;} is a lambda expression and per [expr.prim.lambda.closure]/1:

The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below.

So, for each lambda expression, even if it is identical to a previous one, you will get a unique type.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: