Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lambdas in unevaluated contexts (Until C++20)

I am currently reading P0315R1 paper which talks about Lambdas in unevaluated contexts

There is a statement in the document which explains why lambdas can't appear in unevaluated contexts (of course only until C++20) as below:

Lambdas are a very powerful language feature, especially when it comes to using higher-order algorithms with custom predicates or expressing small, disposable pieces of code. Yet, they suffer from one important limitation which cripples their usefulness for creative use cases; they can’t appear in unevaluated contexts. This restriction was originally designed to prevent lambdas from appearing in signatures, which would have opened a can of worm for mangling because lambdas are required to have unique types.

Can somebody please explain this statement with an example?

like image 478
cpp_enthusiast Avatar asked Apr 17 '19 07:04

cpp_enthusiast


1 Answers

A little background: Linkers don't understand function overloading - they only understand function names like in the C language. That's why C++ compilers mangle your function names. void foo(int) becomes _Z3fooi. The mangled name encodes the types of all the arguments. If your function resulted from a template instantiation, all template arguments get encoded too. If they are themselves template classes, their template arguments get encoded, and so on recursively until the primitive types like ints or function pointers are reached.

Lambdas make this challenging because each lambda is required to have distinct type. This isn't too bad for lambdas defined in functions:

auto foo() { return [](){}; }
auto bar() { return [](){}; }

foo and bar return different types. If you then pass them to another function template, that template's name is mangled as if with foo::__lambda1 or something to that effect.

Letting lambdas appear in decltype would break this mechanism.

void bar(decltype([](){}));
void bar(decltype([](){})) {}

Is this a prototype and a definition? Or are these two different overloads of bar? How to identify them across translation units (how to mangle the names)?

Until now, C++ forbid even asking this question. The paper you linked gives an answer: things like this can't have linkage. Don't even try to mangle them.

like image 78
Filipp Avatar answered Sep 28 '22 07:09

Filipp