Разве постоянная оценка не доставляет удовольствия?
В языке есть несколько мест, где мы пытаемся выполнять постоянную оценку, и если это не удается, мы возвращаемся к непостоянной оценке. Статическая инициализация — одно из таких мест, инициализация постоянных целых чисел — другое.
Что происходит с:
int const i = f();
заключается в том, что это может быть постоянной оценкой, но это не обязательно. Поскольку (не-constexpr
) целые числа-константы по-прежнему можно использовать в качестве константных выражений, если они удовлетворяют всем остальным условиям, мы должны попробовать. Например:
const int n = 42; // const, not constexpr
std::array<int, n> arr; // n is a constant expression, this is ok
Так что попробуем сделать - вызовем f()
как постоянное выражение. В этом контексте std::is_constant_evaluated()
равно true
, поэтому мы попали в ветку с throw
и в итоге потерпели неудачу. Невозможно throw
во время постоянной оценки, поэтому наша постоянная оценка завершается ошибкой.
Но затем мы отступаем и пытаемся снова — на этот раз вызывая f()
как непостоянное выражение (т. е. std::is_constant_evaluated()
равно false
). Этот путь завершается успешно, что дает нам 1
, поэтому i
инициализируется значением 1
. Но примечательно, что i
не является константным выражением на данный момент. Последующее static_assert(i == 1)
будет иметь неверный формат, потому что инициализатор i
не является константным выражением! Даже несмотря на то, что неконстантный путь инициализации (в противном случае) полностью удовлетворяет требованиям константного выражения.
Обратите внимание, что если бы мы попытались:
constexpr int i = f();
Это не удалось бы, потому что мы не можем вернуться к непостоянной инициализации.
person
Barry
schedule
06.09.2019
constexpr
, создающую вторую программу UB. - person NathanOliver   schedule 06.09.2019i
аннотированconstexpr
, то он не скомпилируется. - person Pilar Latiesa   schedule 06.09.2019