Ответ 1
clang верен, обратите внимание, что HEAD-версия gcc accepts также принимает этот код. Это хорошо сформированная функция constexpr, если есть значение для аргумента (ов), которое позволяет оценивать функцию как основное константное выражение. В вашем случае 1
такое значение.
Это описано в стандартном разделе проекта С++ 14 7.1.5
Спецификатор constexpr [dcl.constexpr], который сообщает нам, что разрешено в функции constexpr:
Определение функции constexpr должно удовлетворять следующим ограничениям:
он не должен быть виртуальным (10.3);
его тип возврата должен быть литеральным типом;
каждый из его типов параметров должен быть литеральным типом;
его тело-функция должно быть = delete, = default или составной оператор, который не содержит
определение asm,
инструкция goto,
блок try или
определение переменной нелитерального типа или статической или длительности хранения потоков или для которой инициализация не выполняется.
нет ограничений на throw
, и он также говорит (внимание мое):
Для несимвольной, не дефолтной функции constexpr или не-шаблона, не дефолтного, не наследующего constexpr constructor, , если значения аргумента отсутствуют, так что вызов функции или конструктора может быть оцененным подвыражением основного константного выражения (5.19), программа плохо сформирована; нет требуется диагностика.
и ниже этого параграфа мы имеем следующий пример, похожий на ваш:
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
throw
не разрешено в основном константном выражении, которое рассматривается в разделе 5.19
[expr.const] paragraph 2
, в котором говорится:
Условное выражение e является выражением постоянной константы, если оценка e, следуя правилам абстрактная машина (1.9), оценила бы одно из следующих выражений
и включает следующую марку:
- выражение throw (15.1).
и поэтому f
не будет использоваться в основном постоянном выражении, когда n <= 0
.
Обновить
Как указывает TemplateRex, для этого есть два отчета об ошибках gcc:
- Никогда не выполняемый "throw" в функции constexpr не компилируется
- С++ 14] throw-expression не является допустимым константным выражением
TemplateRex также отмечает, что исправления не применяются к 5.3.0
и находятся только в соединительной линии. Нет, рабочие места предоставляются.