#c #lambda #language-lawyer #constexpr
Вопрос:
Лямбда operator()
-выражение неявно constexpr
соответствует https://en.cppreference.com/w/cpp/language/lambda
Когда этот спецификатор (
constexpr
) отсутствует, оператор вызова функции или любая конкретная специализация шаблона оператора будетconstexpr
в любом случае, если это удовлетворяет всемconstexpr
требованиям к функциям
И требование a constexpr
-функции в соответствии с https://en.cppreference.com/w/cpp/language/constexpr
существует по крайней мере один набор значений аргументов, таких, что вызов функции может быть вычисленным подвыражением основного выражения константы (для конструкторов достаточно использовать в инициализаторе константы) (начиная с C 14). Для нарушения этой пули не требуется никакой диагностики.
В следующем примере функция t()
всегда создает исключение, вызывая лямбда l()
:
auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }
GCC отклоняет эту функцию с ошибкой:
call to non-'constexpr' function '<lambda()>'
но Clang принимает программу (до тех пор, пока функция t()
не будет использоваться в постоянной оценке), что означает, что она рассматривает l()
a constexpr
-функцию, демонстрацию: https://gcc.godbolt.org/z/j1z7ee3Wv
Является ли это ошибкой в Clang, или такое поведение компилятора также приемлемо?
Комментарии:
1. Как говорится в вашей цитате: для нарушения этой пули не требуется никакой диагностики.
2. Отсутствие необходимой диагностики, похоже, на самом деле не отвечает на этот вопрос. Декларация хорошо оформлена. Может ли компилятор неявно пометить такой оператор вызова как constexpr? По тексту он должен быть помечен как не-constexpr, но это трудно реализовать. Заметна ли вообще разница?
Ответ №1:
Все три компилятора выдают ошибку, когда вы на самом деле пытаетесь использовать результат t()
в контексте, требующем постоянного выражения. Например:
auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }
template <bool x>
struct dummy {};
int main() {
dummy< t() > d; // error: t() is not a constant expression
}
Как упоминалось в комментарии НатаноЛивера, в вашей цитате уже говорится:
[…] Для нарушения этой пули не требуется никакой диагностики.
Компиляторам необязательно доказывать, что нет набора значений аргументов, позволяющих функции возвращать постоянное выражение. С другой стороны, компилятор может легко проверить для данного значения аргумента, что результат не является постоянным выражением.