Что в точности означает [decl.constexpr].5?
Стандарт функций constexpr утверждает в пункте 5 [decl.constexpr]:
Для нешаблонной, нестандартной функции constexpr или нешаблонного, нестандартного, ненаследующего конструктора constexpr, если не существует значений аргументов, так что вызов функции или конструктора может быть вычисленным подвыражением основной константы выражение (5.19), программа некорректна; диагностика не требуется.
Далее приводится следующий пример для этого:
constexpr int f(bool b){ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
Из этого я понимаю, что функции с пустыми списками аргументов плохо сформированы без диагностики. Это кажется мне крайне странным, так что я подозреваю, что мое понимание неверно. Например, было бы это тоже неправильно сформировано:
constexpr int g() { return 0; } // ill-formed?
Если да, то каково объяснение этого, и если нет, что означает квалификация / когда функция constexpr становится плохо сформированной?
Предположительно следующие в порядке?
constexpr int h(int x) { return x; } // presumably fine?
constexpr int l = h(42); // also fine
1 ответ
Обоснование этого правила состоит в том, что должен быть хотя бы один контекст, в котором функция может быть оценена вconstexpr
контекст. например, данный:
constexpr int f(bool b){ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
Нет возможности вызвать f()
в constexpr
context, поскольку все пути через эту функцию заканчиваются выражением, которое не является основным постоянным выражением.
Компилятор должен будет оценить все возможные вызовы, чтобы увидеть, можно ли каким-либо образом использовать функцию вconstexpr
контекст. В целом это нелегко диагностировать, поэтому язык говорит, что это плохо сформировано - диагностика не требуется, то есть вы сделали что-то не так, но компилятор не может это диагностировать.
Обратите внимание, что если перегрузка нулевого аргумента f
было следующее:
constexpr int f() { return f(false); } // ok
это было бы прекрасно, так как оценка заканчивается выражением-константой ядра.
Аналогично эта функция:
constexpr int g() { return 0; } // ok
а также этот:
constexpr int h(int x) { return x; } // ok
constexpr int l = h(42); // ok
в порядке, так как g
а также h
может быть вызван в constexpr
контекст.
Формулировка "... если не существует таких значений аргумента, что..." может сбивать с толку, поскольку вы спрашивали о правильности форматаg
. Ноg
может быть вызван с нулевыми аргументами, или другими словами, с void
аргумент, так что все в порядке.