Vincent
Vincent

Reputation: 60361

Static (possibly constexpr) data member lambda

The following code does not compile:

struct object 
{
    static constexpr auto f;
};

constexpr auto object::f = [](auto&& x){x += 1;};

neither this one:

struct object 
{
    static constexpr auto f = [](auto&& x){x += 1;};
};

but this does (when f is not a member):

static constexpr auto f = [](auto&& x){x += 1;};

Is there a way to declare and define a static constexpr data member lambda in C++14?

Upvotes: 3

Views: 1045

Answers (1)

Barry
Barry

Reputation: 302758

The rule on static data members is in [class.static.data]:

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (5.19). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression.

Only static const integral/enumeration types or constexpr members can be defined within the class definition. C++14 disallowed constexpr lambdas period. The wording in [expr.const] used to read:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:
— [...]
— a lambda-expression (5.1.2);
— [...]

So in C++14, you just can't have a static lambda data member - you can't define it inline and you can't define it out of line because you have no way of declaring it (variables declared with auto require an initializer). You're out of luck.


In C++17, we can have constexpr lambdas thanks to p0170, at which point your second option is fine:

struct object 
{
    static constexpr auto f = [](auto&& x){x += 1;};
};

Upvotes: 4

Related Questions