Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do non-local C++11 lambdas live in anonymous namespaces?

A recent build of GCC 4.8 gives the following code, when in a header file:

auto L = [](){};

struct S
{
    decltype(L) m;
};

the 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 type of the lambda to use the anonymous namespace? I made the lambda global, I didn't use an anonymous namespace anywhere.

UPDATE: The compiles gives the same warning even if I put the lambda in an explicit namespace, like so:

namespace N
{
    auto L = [](){};
}

struct S
{
    decltype(N::L) m;
};

UPDATE 2: In fact, it seems even class scope lambdas have the same problem:

class N
{
    static constexpr auto L = [](){};
};

struct S
{
    decltype(N::L) m;
};
like image 235
HighCommander4 Avatar asked Jul 18 '12 04:07

HighCommander4


People also ask

What is the point of anonymous namespaces?

An anonymous namespace makes the enclosed variables, functions, classes, etc. available only inside that file. In your example it's a way to avoid global variables.

How are lambdas stored?

The Lambda service stores your function code in an internal S3 bucket that's private to your account. Each AWS account is allocated 75 GB of storage in each Region. Code storage includes the total storage used by both Lambda functions and layers.

Are lambdas functors?

We have seen that lambda is just a convenient way to write a functor, therefore we should always think about it as a functor when coding in C++. We should use lambdas where we can improve the readability of and simplify our code such as when writing callback functions.

What is lambda function in C++11?

Lambdas can both capture variables and accept input parameters. A parameter list (lambda declarator in the Standard syntax) is optional and in most aspects resembles the parameter list for a function. C++ Copy. auto y = [] (int first, int second) { return first + second; };


2 Answers

§5.1.2/3:

The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed nonunion class type — called the closure type — whose properties are described below. This class type is not an aggregate (8.5.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.

So, unless you're defining the lambda expression in code inside an anonymous namespace, the lambda's type should not be contained in an anonymous namespace either.

like image 71
Jerry Coffin Avatar answered Sep 21 '22 06:09

Jerry Coffin


Unless I missed something, none of these should be in an anonyous namespace, though atleast both GCC and MSVC seem to put them there.

§5.1.2 [expr.prim.lambda] p3

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

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

(You can test in which namespace a lambda type resides by simply containing the lambda in some kind of warning / error producing code. The compiler should spit out its type along with the warning / error.)

like image 38
Xeo Avatar answered Sep 20 '22 06:09

Xeo