нет этого не может быть, потому что не каждый inovocation функции constexpr должен быть в состоянии оценить как подвыражение основного постоянного выражения. Нам нужно только одно значение аргумента, которое позволяет это. Таким образом, функция constexpr может содержать оператор throw, если у нас есть значение аргумента, которое не вызывает эту ветвь.
Это предусмотрено в проекте C++ 14 стандартный раздел 7.1.5
constexpr спецификатор [dcl.constexpr], который говорит нам о том, что разрешено в функции constexpr:
Определение функции constexpr должны удовлетворять следующие ограничения:
не должно быть виртуальным (10.3);
его тип возврата должен быть буквальным;
каждый из его типов параметров должен быть буквальным;
его функция тело должно быть = удаление, = по умолчанию, или соединение-заявление, которое не содержит
, который, как мы видим, не запрещает throw
и фактически запрещает очень мало, так как Relaxing constraints on constexpr functions предложение стало частью C++ 14.
Ниже мы видим правило, которое гласит функция constexpr хорошо формируется, если по меньшей мере одно значение аргумента существует такое, что оно может быть оценено как подвыражение из основного константного выражения:
For A не- шаблон, не-дефолтная функция 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
Таким образом, мы ожидаем, что выход на следующем примере:
#include <iostream>
constexpr int f(bool b) { return b ? throw 0 : 0; }
int main() {
std::cout << noexcept(f(1)) << "\n"
<< noexcept(f(0)) << "\n" ;
}
(see it live with gcc):
0
1
Visual Studio через webcompiler также дает тот же результат. Как отмечал hvd, clang имеет ошибку, о чем свидетельствует отчет об ошибке noexcept should check whether the expression is a constant expression.
Дефект Report 1129
Defect report 1129: Default nothrow for constexpr functions задает тот же вопрос:
Функция constexpr не разрешается возвращаться через исключение.Это должно быть распознано, а функция, объявленная constexpr без явной спецификации исключения, должна обрабатываться как объявленная noexcept (true), а не обычная noexcept (false). Для шаблона функции, объявленного constexpr без явной спецификации исключения, его следует считать noexcept (true) тогда и только тогда, когда ключевое слово constexpr соблюдается при заданном экземпляре.
и ответ был:
Предпосылка не является правильным: исключение запрещено только тогда, когда функция constexpr вызывается в контексте, который требует постоянного выражения. Используется как обычная функция, она может бросать.
и модифицированные 5.3.7 [expr.unary.noexcept] пункт 3 пули 1 (добавление с акцентом отметил):
потенциально оценивали call80 к функции, функции-члена, функция указатель, или указатель на функцию элемента, который не имеет не-метательные исключения спецификации (15,4 [except.spec]), , если вызов не является постоянным выражением (5.20 [expr.const]),
@ cad anyways t он вопрос очень общий, не думаю, что есть хороший конкретный пример. – Orient
Counter-example: 'constexpr void * foo (int n) {return n == 0? nullptr: operator new (n); } '. [Демо] (https://ideone.com/zlTsDI). –
Я сделал это один раз, см. Http://stackoverflow.com/a/13305072/34509 –