2017-02-02 20 views
7

Почему и как это работает? Какой тип 'авто'?Почему лямбда-выражение возвращает локальный тип класса enum?

auto lambda = [](){ 
    enum class Local { X=0 }; 
    return Local::X; 
}; 

auto x = lambda(); // No error! Why and what type is auto in this case? 
auto y = Local::X; // Error! Of course! 

The enum class Local не известен за пределами лямбды типа. Это enum class и поэтому не может быть типа int без литья, AFAIK. Как можно вернуть локальный тип как auto и какой тип он действительно находится за пределами лямбда?

ответ

4

Why and how does this work?

Это работает, потому что:

  • лямбда-выражение вызывает уникальный класс быть создан и назван во время компиляции.
    • Тип этого класса указан внутренним компилятором.
    • Следовательно, компилятор может придумать что-то вроде <lambda_30560bd1c97ca682d011cd006c362574>::()::Local для x.

Вы можете получить тип лямбды, а затем использовать его для объявления объектов типа enum class, содержащегося в ней:

auto lambda = []() { 
    enum class Local { X = 0, Z = 1 }; 
    return Local::X; 
}; 

int main() { 
    auto x = lambda(); // No error! Why and what type is auto in this case? 
    //auto y = Local::X; // Error! Of course! 
    using x_type = decltype(x); 
    x_type y; 
    y = x_type::Z; // can refer to enum members here 
    y = x; 
} 

The enum class Local is not known outside the lambda a type.

Правда, но enum class доступен, если соответствующее пространство имен будет разрешено. Поэтому внутренне <lambda_30560bd1c97ca682d011cd006c362574>::()::Local может разрешить Local внутри лямбда, но это невозможно догадаться до компиляции, но мы можем использовать decltype или auto, чтобы получить тип.

It's a enum class and therefore cannot be of type int without a cast

Исправить. Но он все еще существует так же, как enum class может существовать внутри обычного class или struct.

Without a known type, how can I continue work with that value outside the lambda?

Утилита этого типа за пределами лямбда ограничена. Это не int, а скорее имеет свой собственный уникальный тип, поэтому он будет иметь мало значения, даже если он может быть косвенно получен.

+1

Вы используете ** можете ** несколько раз. Это просто догадка? Это своего рода стирание типа, потому что без ** известного типа **, как я могу продолжить работу с этим значением за пределами лямбда? Рассматривается ли он, например. a 'int' как базовый тип автоматически? Извините, ваш ответ не удовлетворяет. – cwschmidt

+0

Какой компилятор вы используете? 'using x_type = typename decltype (x);' похоже, не работает с GCC. ("главный.cpp: 10: 29: ошибка: ожидаемый вложенный имя-спецификатор перед 'decltype' с использованием x_type = typename decltype (x); ") – cwschmidt

+1

@cwschmidt это просто' using x_type = decltype (x); 'no need for' typename ' –

5

Это не имеет ничего общего с лямбдой или enum class эсов, это работает для любого локального типа в любой функции с выведенным типом возвращаемого значения:

auto f() { 
    struct X {}; 
    return X{}; 
} 

int main() { 
    auto x = f(); 
} 

Тип x не может быть отнесен непосредственно к из-за пределы области видимости функции, но это действительно X, определенный в пределах f.