Статический массив лямбда-функций (C++)

Я хотел бы сделать что-то вроде этого (внутри класса):

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

здесь MyStruct определено как:

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

Я тоже пробовал:

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

определение fn, но не повезло.

ошибка, которую я получаю для первого случая, -"ошибка: инициализатор поля не является постоянной" чего я на самом деле не понимаю. Если я попытаюсь с std::function это становится хуже, так как он говорит: "не может быть инициализирован непостоянным выражением, когда объявленный."

почему лямбда-функция непостоянна? Я что-то упускаю?

2 ответов


при создании constexpr объект, все, что вы передаете в него, должно быть основным постоянным выражением, [decl.constexpr] / 9:

A constexpr спецификатор, используемый в объявлении объекта, объявляет объект как const. Такой объект должен иметь литеральный тип и должен быть инициализирован. Если он инициализируется вызовом конструктора,этот вызов должен быть постоянным выражением (5.19).

and, from [expr.const] лямбды не постоянны выражения1:

A условное выражение e это выражение константы ядра если оценка e, следуя правилам абстрактная машина (1.9), будет оценивать одно из следующих выражений:

  • [...]
  • лямбда-выражения (5.1.2);
  • [...]

однако это применимо только к constexpr, а не const, поэтому вы могли бы просто сделать это вместо этого:

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

Примечание: ваши лямбды не нужно ничего захватывать, так что вы должны просто пустой список захвата [].


1As dyp указывает, есть предложение изменить это: N4487

захват лямбда не может распадаться на указатель функции.

и оператор для возврата указателя функции из (не захвата) лямбда не constexpr.