11

I'd like to do something like this (inside a class):

static constexpr MyStruct ops[6] = {
    {'+', [&] (double a, double b) { return a+b; } },
    {'-', [&] (double a, double b) { return a-b; } },
    ...
};

Where MyStruct is defined as:

typedef double (*binOp)(double, double);
struct MyStruct {
    char c;
    binOp fn;
};

I also tried:

std::function <double(double,double)> fn;

for the definition of fn, but no luck.

The error I get for the first case is "error: field initializer is not constant" which I don't really get. If I try with std::function it gets worse, since it says: "cannot be initialized by a non-constant expression when being declared".

Why is the lambda function non-constant? Am I missing something?

4
  • 1
    Replace constexpr with const. Commented May 29, 2015 at 11:07
  • 4
    lambda-expressions currently may not occur inside constant expressions, but that restriction might get removed eventually: isocpp.org/files/papers/N4487.pdf Commented May 29, 2015 at 11:11
  • 1
    From C++17, please note that lambdas can now be constexpr: stackoverflow.com/questions/6420085/… Commented Jan 17, 2019 at 15:27
  • 1
    Also note your lambda's capture everything in their scope by reference. Currently they don't use anything so it's not a problem, but capturing lambda's are not convertible to a raw function pointer. Commented Mar 17, 2020 at 12:56

2 Answers 2

8

When you construct constexpr object, everything you pass into it needs to be a core constant expression, [decl.constexpr]/9:

A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression (5.19).

and, from [expr.const] lambdas are not constant expressions1:

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);
  • [...]

However, that applies only to constexpr and not to const, so you could simply do that instead:

static const MyStruct ops[6] = {
    {'+', [] (double a, double b) { return a+b; } },
    {'-', [] (double a, double b) { return a-b; } },
};

Note: your lambdas don't need to capture anything, so you should just empty the capture list [].


1As dyp points out, there is a proposal to change this: N4487

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

Comments

1

capturing lambda cannot decay to function pointer.

and operator to return the function pointer from a (non-capturing) lambda is not constexpr.

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.