Можно ли предположить, что идентичные лямбда-выражения имеют разные типы?
Я экспериментирую с лямбдами и тем, что разные лямбда-выражения имеют разные типы, хотя они одинаковы. Рассмотрим этот код
#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
}
Это печатает 112
, то есть a
и b
, конечно, одного типа, а c
имеет другой тип.
Разрешено ли компилятору c
быть того же типа, a
?
Я имею в виду, что выражения идентичны, и это будет очевидная оптимизация.
PS: Если захват предотвращает такую оптимизацию, то как насчет лямбда без захвата?
related: что такое подпись типа lambda-функции С++ 11/1y? и может ли выражаться "тип" лямбда-выражения?
Ответы
Ответ 1
Разрешено ли компилятору c
быть того же типа, a
?
№ [&counter](){counter++;}
- это лямбда-выражение и в [expr.prim.lambda.closure]/1:
Тип лямбда-выражения (который также является типом объекта замыкания) - это уникальный, неназванный тип неединичного класса, называемый типом замыкания, свойства которого описаны ниже.
Таким образом, для каждого лямбда-выражения, даже если оно идентично предыдущему, вы получите уникальный тип.