Why am I getting a type inference error for a lambda that returns a lambda with multiple return paths?

I have the following code:

int main() { auto f = [] { if (1) return [] { return 1; }; else return [] { return 2; }; }; return f()(); } 

which causes the following compiler error using GCC 5.2.1:

 error: inconsistent types 'main()::<lambda()>::<lambda()>' and 'main()::<lambda()>::<lambda()>' deduced for lambda return type else return [] { return 2; }; 

Now itโ€™s obvious that these two types look the same, so I'm not sure if this is GCC with an error message or if it is actually an error. To my knowledge, this should compile; lambda return type must be equal to std::function<int()> . Interestingly, if I pre-declare a lambda return and return the same variable twice, it works.

Can anyone shed light on what is happening? I found similar questions, many of which are related to GCC errors, but it looks different.

+6
source share
3 answers

Now itโ€™s obvious that these two types are the same,

No, it is not. The type of each lambda expression is a unique, separate type.

From [expr.prim.lambda] / 3:

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

Therefore, returning the type of the return value for f fails and does not result in std::function<int()> . The latter is an unrelated type of library, which is somehow not magically a โ€œcommon typeโ€ of any type of closure.

Of course, each of the unique closure types can be converted to std::function<int()> , so if you provide a return type, everything works:

 auto f = []() -> std::function<int()> { return 1 ? []() { return 1; } : []() { return 2; }; }; 

Or, as a simple function:

 std::function<int()> f() { return 1 ? []() { return 1; } : []() { return 2; }; } 
+13
source

Each lambda has its own unique type:

The lambda expression creates an unnamed temporary object prvalue a unique unnamed non-unit non-aggregate type [...].

From here , emphasize mine.

In addition, lambdas has nothing to do with std::function , it is a different type. In particular,

 [] { return 1; } 

and

 [] { return 2; } 

have different types. That is why deduction fails.

+2
source

These types do not match. Each lambda is an instance of a unique, unnamed type. std::function is a template that can be implicitly converted from the corresponding called objects, including lambdas, but no instantiation of std::function is the type or parent type of any lambda, so it cannot be deduced.

However, you can tell the compiler that you want to return std::function , and it will work:

 auto f = []() -> std::function<int()> { if (1) return [] { return 1; }; else return [] { return 2; }; } 
+1
source

All Articles