Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can a lambda expression return a local enum class type?

Why and how does this work? What type is 'auto' here?

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 is not known outside the lambda a type. It's a enum class and therefore cannot be of type int without a cast, AFAIK. How can a local type be returned as auto and what type is it really outside the lambda?

like image 645
cwschmidt Avatar asked Feb 02 '17 20:02

cwschmidt


People also ask

Does lambda function have return type?

The return type for a lambda is specified using a C++ feature named 'trailing return type'. This specification is optional. Without the trailing return type, the return type of the underlying function is effectively 'auto', and it is deduced from the type of the expressions in the body's return statements.

Do lambdas go out of scope?

A lambda object must not outlive any of its reference captured objects. Lambda expressions may capture objects with automatic storage duration from the set of enclosing scopes (called the reaching scope) for use in the lambda's function body.

How do you write a lambda function in C++?

Creating a Lambda Expression in C++auto greet = []() { // lambda function body }; Here, [] is called the lambda introducer which denotes the start of the lambda expression. () is called the parameter list which is similar to the () operator of a normal function.


2 Answers

This has nothing to do with lambdas or enum classes, this works for any local type in any function with deduced return type:

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

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

Type of x cannot be directly referred to from outside function scope, but it is indeed X defined within f.

like image 116
yuri kilochek Avatar answered Sep 29 '22 05:09

yuri kilochek


Why and how does this work?

It works because:

  • a lambda expression causes a unique class to be generated and named at compile time.
    • The type of this class is named by the compiler internally.
    • Hence the compiler may come up with something like <lambda_30560bd1c97ca682d011cd006c362574>::()::Local for x.

You could obtain the lambda's type and then use that to declare objects of the type of the enum class contained within it:

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.

True, but the enum class is accessible if the relevant namespace is resolved. So internally <lambda_30560bd1c97ca682d011cd006c362574>::()::Local can resolve to Local inside the lambda, but it is not possible to guess this name before compilation, but we could use decltype or auto to get the type.

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

Correct. But it still exists in the same way that an enum class could exist inside of a regular class or struct.

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

The utility of this type outside of the lambda is limited. It is not an int, but rather has its own unique type and so it would be of little value even though it can be indirectly obtained.

like image 24
wally Avatar answered Sep 29 '22 07:09

wally