Вот как я об этом думаю, может быть, вы найдете это полезным ... может быть, нет. Обратите внимание, что я думаю, что написание if constexpr (std::is_constant_evaluated())
будет действительно распространенной ошибкой, и попасть в нее легко. Но, надеюсь, компиляторы просто диагностируют этот случай.
<час />
По сути, у нас есть два разных правила для кода - типичные правила для нормального кода времени выполнения и ограничения для константных выражений, которые применяются для программирования constexpr
. Это ограничения expr.const: нет UB, нет reinterpret_cast
и т. Д. Эти ограничения продолжают уменьшаться от языкового стандарта к языковому стандарту, что замечательно.
По существу, поток управления (с точки зрения пути кода) чередуется между режимом «полного времени выполнения» и режимом constexpr
. Как только мы войдем в режим constexpr
(будь то инициализация объекта constexpr
или оценка параметра шаблона или ...), мы останемся там, пока не закончим ... и затем вернемся к полному режиму выполнения.
Что делает is_constant_evaluated()
просто: я в режиме constexpr? Он сообщает вам, если вы находитесь в контексте, который требует константных выражений.
В этом представлении давайте рассмотрим if constexpr (is_constant_evaluated())
. Независимо от того, в каком состоянии мы были, if constexpr
требует постоянного выражения в качестве инициализированного, так что это переводит нас в режим constexpr, если мы еще не были там. Следовательно, is_constant_evaluated()
просто верно - безусловно.
Однако для if (is_constant_evaluated())
простой if
не меняет наше состояние между временем выполнения и constexpr. Таким образом, значение здесь зависит от контекста, из которого он был вызван. Инициализация test4
переводит нас в режим constexpr, потому что это объект constexpr. Во время его инициализации мы следуем правилам константных выражений ... так что is_constant_evaluated()
верно. Но как только мы закончим, мы вернемся к правилам времени выполнения ... поэтому при инициализации test5
, is_constant_evaluated()
ложно. (И тогда test6
является особым случаем неудачного языка - вы можете использовать постоянные целочисленные переменные в качестве константных выражений, поэтому мы используем их инициализацию одинаково для этих целей.)