std :: is_constant_evaluated поведение - PullRequest
0 голосов
/ 18 января 2019

GCC9 уже реализует std::is_constant_evaluated. Я немного поиграл с этим, и понял, что это несколько сложно. Вот мой тест:

constexpr int Fn1()
{
  if constexpr (std::is_constant_evaluated())
    return 0;
  else
    return 1;
}

constexpr int Fn2()
{
  if (std::is_constant_evaluated())
    return 0;
  else
    return 1;
}

int main()
{
  constexpr int test1 = Fn1(); // Evaluates to 0
  int test2 = Fn1();           // Evaluates to 0
  int const test3 = Fn1();     // Evaluates to 0

  constexpr int test4 = Fn2(); // Evaluates to 0
  int test5 = Fn2();           // Evaluates to 1
  int const test6 = Fn2();     // Evaluates to 0
}

По этим результатам я извлек следующие выводы:

  • if constexpr (std::is_constant_evaluated()) всегда оценивает true филиал. Следовательно, нет смысла использовать эту конструкцию.

  • Если компилятор оценивает переменную во время компиляции, std::is_constant_evaluated()) - это true, независимо от того, переменная явно аннотирована constexpr или нет.

Я прав?

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Вот как я об этом думаю, может быть, вы найдете это полезным ... может быть, нет. Обратите внимание, что я думаю, что написание 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 является особым случаем неудачного языка - вы можете использовать постоянные целочисленные переменные в качестве константных выражений, поэтому мы используем их инициализацию одинаково для этих целей.)

0 голосов
/ 18 января 2019

if constexpr требует константного выражения для условия. Так что is_constant_evaluated, конечно, всегда будет правдой в таком контексте.

Это предназначено для обычного if. Цель состоит в том, чтобы не входить в путь кода, который недопустим в функции constexpr при оценке в константном выражении. Но чтобы он выполнялся во время выполнения. Это не для того, чтобы полностью исключить эти пути кода из функции.

...