Illegal C ++ 11 lambdas live in anonymous namespaces?

In a recent build of GCC 4.8, the following code is shown if in the header file:

auto L = [](){}; struct S { decltype(L) m; }; 

following warning:

 test.hpp:3:8: warning: 'S' has a field 'S::m' whose type uses the anonymous namespace [enabled by default] struct S ^ 

Why does the compiler consider the lambda type to use an anonymous namespace? I made a global lambda, I did not use an anonymous namespace anywhere.

UPDATE Compilations give the same warning even if I put lambda in an explicit namespace, for example:

 namespace N { auto L = [](){}; } struct S { decltype(N::L) m; }; 

UPDATE 2 : in fact, it seems that the class lambdas class also has the same problem:

 class N { static constexpr auto L = [](){}; }; struct S { decltype(N::L) m; }; 
+6
source share
4 answers

GCC's warning might be a bit confusing, but his intent is certainly true. The lambda type is not specified, and it is unique throughout the program. On the other hand, if your class is not placed in an unnamed namespace (which, according to your description, I guess not), your class is the same type in every translation unit in which you include it. Since the same class must have the same members and not different members in different translation units, this is a violation (and leads to undefined behavior).

At least so that L is extern , so you get "multiple definitions of L" linker errors after including the header in several translation units.

+1
source

Β§5.1.2 / 3:

The type of lambda expression (which is also the type of the closure object) is a unique, unnamed non-runtime type of the class - called the closure type - whose properties are described below. This type of class is not a collection (8.5.1). The type of closure is declared in the smallest area of ​​the block, in the class or in the namespace that contains the corresponding lambda expression.

So, if you do not define the lambda expression in the code inside the anonymous namespace, then the lambda type should not be contained in the anonymous namespace.

+7
source

If I didn't miss anything, none of them should be in a space with an anonymous namespace, although at least both GCC and MSVC seem to put them there.

Β§5.1.2 [expr.prim.lambda] p3

[...] The type of closure is declared in the smallest area of ​​the block, the scope of the class or namespace that contains the corresponding lambda expression. [...]

Atleast Clang seems to be right, the closure type is where it should be.

(You can check in which namespace the lambda type is located, which simply contains the lambda in the code of the warning or error code. The compiler should throw out its type along with the warning / error.)

+4
source

I did not read the specification in this case, just thought ... but can you do a test?

Your lambda is too trivial and could turn into a stateless stateless person. Agents that have no analogues like yours can turn into a simple C-function by a compiler. There may be some rule to put these functions in an anonymous namespace so that they exist in only one compilation unit.

Therefore, I suggest you do it without statelessness, for example, refer to a variable, and see if it is still in this anonymous namespace.

0
source

Source: https://habr.com/ru/post/920766/


All Articles