Вот что я думаю об этом, может быть, вы найдете это полезным... а может и нет. Обратите внимание, что я думаю, что запись if constexpr (std::is_constant_evaluated())
будет очень распространенной ошибкой, и в эту ловушку легко попасть. Но, надеюсь, компиляторы просто диагностируют этот случай. Отправлено 91428, что исправлено для gcc 10.1.
По сути, у нас есть два разных правила для кода — типичные правила для обычного кода времени выполнения и ограничения для константных выражений, которые предназначены для 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()
равно false. (И тогда test6
является неудачным частным случаем языка — вы можете использовать константные целочисленные переменные в качестве константных выражений, поэтому мы одинаково относимся к их инициализации для этих целей.)
person
Barry
schedule
18.01.2019
<type_traits>
и параметр компилятора-std=c++2a
- person metalfox   schedule 18.01.2019