74
struct Test
{
  static const int value = []() -> int { return 0; } ();
};

With gcc-4.6 I get something like, error: function needs to be constexpr. I have tried multiple combinations of putting constexpr at various places, but no luck.

Is constexpr supported for lambda functions as well (irrespective of return type specified or not) ? What is the correct syntax ?

Any work around possible ?

4

5 Answers 5

43

Update: As of C++17, lambdas are permitted in constant expressions.


Lambdas are currently (C++14) not allowed in constant expressions as per [expr.const]/(2.6), but they will once N4487 is accepted (which can be found in the working draft N4582):

This proposal suggests allowing lambda-expressions in constant expressions, removing an existing restriction. The authors propose that certain lambda-expressions and operations on certain closure objects be allowed to appear within constant expressions. In doing so, we also propose that a closure type be considered a literal type if the type of each of its data-members is a literal type; and, that if the constexpr specifier is omitted within the lambda-declarator, that the generated function call operator be constexpr if it would satisfy the requirements of a constexpr function (similar to the constexpr inference that already occurs for implicitly defined constructors and the assignment operator functions).

Sign up to request clarification or add additional context in comments.

2 Comments

I suppose making lambdas constexpr is a necessary step towards making STL algorithms constexpr as well since STL algorithms frequently take lambdas as arguments. Many (all?) of them were indeed made constexpr in C++20.
@AnthonyD973 constexpr-ification of the library is indeed a major overhaul and will likely be extended to the vast majority thereof.
28

From the C++0x FDIS §7.1.5[dcl.constexpr]/1:

The constexpr specifier shall be applied only to the definition of a variable, the declaration of a function or function template, or the declaration of a static data member of a literal type.

A lambda expression is none of those things and thus may not be declared constexpr.

8 Comments

Workaround for what? What are you trying to accomplish with a constexpr lambda expression? Why can you not use an ordinary function or function template?
I am able to calculate number of __VA_ARGS__ of macro at run time using lambda expression. Just making it constexpr will be a compile time constant. Explaining that will be a detailed new topic. I know that there are boost alternatives available, but the method I have used seems to me very straight forward and handy.
Why not just use a VA_NARGS and do the computation at preprocessing (see the example at the beginning of this answer).
Or how about using variadic templates and sizeof...()? Something like template<typename... Args> Counter { static const size_t N = sizeof...(Args); };, and then use Counter<a,b,c>::N, if your macro arguments are types... or something more elaborate with constexpr size_t f(Args... args) const { return sizeof...(Args); } if your arguments aren't types.
@JosephGarvin yes. Variable templates were added to the things that can be constexpr but nothing regarding lambdas.
|
21

Prior to C++17 lambdas are not compatible with constexpr. They cannot be used inside constant expressions.

Starting with C++17 lambdas are constexpr where it makes sense. The proposal N4487 will be put into the C++17 standard. On his website Herb Sutter, chair of the ISO C++ committee, stated the following:

Lambdas are now allowed inside constexpr functions.

Comments

18

FFWD to year 2018 :)

auto my_const_expression_lambda = []()
  constexpr -> bool
{
   return true ;
}

Since c++17

1 Comment

For reference, see the list of specifiers [specs] on cppreference.
1

I know that this is an old question, but no one specified a workaround for this. The workaround is to use a constexpr functor like so:

struct functor
{
    constexpr int operator()() { return 0; }
};

struct Test
{
  static const int value = functor{}();
};

Not optimal as it moves the code away from where it's used, but when you don't have many options, this is doable. I had to use something similar for a project still compiling with c++14. This simple case has been tested on c++11 here: https://godbolt.org/z/Gvxq19jsd

However, if you have c++17 or higher, using the described:

struct Test
{
  static constexpr int value = []() constexpr { return 0; }();
};

is a nicer option.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.