Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 463
463035818_is_not_a_number Avatar asked May 18 '18 19:05

463035818_is_not_a_number


People also ask

Can different forms of lambda take multiple Python statements expressions?

Lambda functions can have only one expression.

Can lambda function have multiple methods?

Since a lambda function can only provide the implementation for 1 method it is mandatory for the functional interface to have ONLY one abstract method.

Can lambda expressions contain data types?

The lambda expressions have a very simple, precise syntax and provide flexibility to specify the datatypes for the function parameters. Its return type is a parameter -> expression body to understand the syntax, we can divide it into three parts.

How many types of lambda expressions are there?

Types of Lambda Body In Java, the lambda body is of two types. () -> System. out. println("Lambdas are great");


1 Answers

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.

You can use typeid to check that this is the case like:

#include <iostream>
#include <typeinfo>

template <typename T> void once(T t){
    static bool first_call = true;
    std::cout << typeid(t).name() << std::endl;
    if (first_call) {
        t();
    }
    first_call = false;
}

int main() {    
    int counter = 0;
    auto a = [&counter](){counter++;};
    once(a);
    once(a);
    std::cout << counter << std::endl; // 1

    auto b = a;                        // same type
    once(b);
    std::cout << counter << std::endl; // 1

    auto c = [&counter](){counter++;}; // different type
    once(c);
    once(c);               
    std::cout << counter << std::endl; // 2
}

result:

Z4mainEUlvE_                                                                                                          
Z4mainEUlvE_                                                                                                          
1                                                                                                                     
Z4mainEUlvE_                                                                                                          
1                                                                                                                     
Z4mainEUlvE0_                                                                                                         
Z4mainEUlvE0_                                                                                                         
2

and you can see there are two function template instantiations.

like image 56
NathanOliver Avatar answered Nov 09 '22 08:11

NathanOliver