Почему моя функция constexpr не возвращает лямбда?
Я обнаружил, что этот фрагмент кода не работает:
typedef int (*fp)(int a, int b);
constexpr fp addition()
{
return [](int a, int b){ return a+b; };
}
#include <iostream>
int main()
{
fp fun = addition();
std::cout << fun(2,2);
}
Это дает мне ошибку
cexpr.cpp: In function 'constexpr int (* addition())(int, int)':
cexpr.cpp:5:43: error: call to non-constexpr function 'addition()::<lambda(int,
int)>::operator int (*)(int, int)() const'
Почему? Я не называю это здесь.
Работа с прямым подходом:
typedef int (*fp)(int a, int b);
#include <iostream>
int main()
{
fp fun = [](int a, int b){ return a+b; };
std::cout << fun(2,2);
}
Я использую MinGW с g++ версии 4.7.2.
Ответы
Ответ 1
Ваша функция fp()
не возвращает тип литерала, поэтому она не может быть функцией constexpr:
Из раздела 7.1.5: "Определение функции constexpr должно удовлетворять следующим ограничениям:
- он не должен быть виртуальным (10.3);
- его тип возврата должен быть литеральным типом;
- каждый из его типов параметров должен быть литеральным типом;
- его тело функции должно быть = delete, = default, или составной оператор, содержащий только
- null,
- static_assert-декларация
- объявления typedef и псевдонимы-объявления, которые не определяют классы или перечисления,
- с использованием деклараций,
- с использованием Директив,
- и ровно один оператор return;"
Я не думаю, что здесь есть какая-то ошибка, и особенно ничего не связано с лямбдами, как упоминалось в более раннем ответе: переменные просто не могут быть объявлены внутри функции constexpr.
Ответ 2
Согласно N3376 рабочий проект стандартного раздела 5.19 [expr.const]:
В некоторых контекстах требуются выражения, которые удовлетворяют дополнительным требования, подробно описанные в этом подпункте; другие контексты различная семантика в зависимости от того, удовлетворяет ли выражение эти требования. Выражения, удовлетворяющие этим требованиям, называемых постоянными выражениями. [Примечание: константные выражения могут быть оценивается во время перевода. - примечание к концу]
Далее говорится:
Условное выражение является выражением постоянной константы, если оно включает одно из следующего в качестве потенциально оцениваемого подвыражения (3.2), но подвыражения логического И (5.14), логического ИЛИ (5.15), и условные (5.16) операции, которые не оцениваются, не являются рассмотрено [Примечание: перегруженный оператор вызывает функцию.- end примечание]:
Что перечисляет под ним:
- лямбда-выражение (5.1.2);
Поэтому, хотя я не знаю достаточно стандартного, я считаю, что это говорит о том, что constexpr не должен иметь внутри себя лямбда-выражения.
Ответ 3
Сообщение об ошибке gcc дало вам точное и правильное:
error: вызов функции non-constexpr 'add()::
< лямбда (целое, целое) > ::
оператор int (*) (int, int)() const
Я немного переформатировал и добавил акцент. Принуждая лямбда к указателю на функцию, вы неявно вызываете автоматически созданную функцию преобразования от лямбда до pointer to function of type "auto (int, int)->int"
, которая не является функцией constexpr, потому что автоматически созданная функция преобразования не объявляется constexpr
(и стандартная не требует, чтобы это было).