Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static array of lambda functions (C++)

Tags:

c++

c++11

lambda

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?

like image 974
David G.F. Avatar asked May 29 '15 11:05

David G.F.


2 Answers

capturing lambda cannot decay to function pointer.

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

like image 180
Jarod42 Avatar answered Oct 17 '22 00:10

Jarod42


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
like image 42
Barry Avatar answered Oct 17 '22 00:10

Barry