std::is_constant_evaluated
| Определено в заголовочном файле <type_traits>
|
||
constexpr bool is_constant_evaluated() noexcept; |
(начиная с C++20) | |
Определяет, происходит ли вызов функции в контексте с константным вычислением. Возвращает true, если оценка вызова происходит в рамках оценки выражения или преобразования, которые явно вычисляются константно; иначе возвращает false.
Чтобы определить, являются ли инициализаторы следующих переменных явно вычисляемыми константо, компиляторы могут сначала выполнить пробную константную оценку:
- переменные со ссылочным типом или const-квалифицированный целочисленный тип или тип перечисления;
- статические и локальные потоковые переменные
В этом случае не рекомендуется полагаться на результат.
int y = 0;
const int a = std::is_constant_evaluated() ? y : 1;
// Пробная константная оценка не удалась. Константная оценка отбрасывается.
// Переменная a динамически инициализируется 1
const int b = std::is_constant_evaluated() ? 2 : y;
// Константная оценка std::is_constant_evaluated() == true выполняется успешно.
// Переменная b статически инициализируется значением 2
Параметры
(нет)
Возвращаемое значение
true, если оценка вызова происходит в рамках оценки выражения или преобразования, которые явно вычисляются как константы; в противном случае false.
Возможная реализация
// Эта реализация требует C++23, если consteval.
constexpr bool is_constant_evaluated() noexcept
{
if consteval
{
return true;
}
else
{
return false;
}
}
|
Примечание
При непосредственном использовании в качестве условия объявления static_assert или оператора constexpr if, std::is_constant_evaluated() всегда возвращает true.
Поскольку if consteval отсутствует в C++20, std::is_constant_evaluated обычно реализуется используя расширение компилятора.
| Макрос Тестирования функциональности | Значение | Стандарт | Функциональность |
|---|---|---|---|
__cpp_lib_is_constant_evaluated |
201811L |
(C++20) | std::is_constant_evaluated
|
Пример
#include <cmath>
#include <iostream>
#include <type_traits>
constexpr double power(double b, int x)
{
if (std::is_constant_evaluated() && !(b == 0.0 && x < 0))
{
// Контекст константной оценки: используйте алгоритм, дружественный к constexpr.
if (x == 0)
return 1.0;
double r {1.0};
double p {x > 0 ? b : 1.0 / b};
for (auto u = unsigned(x > 0 ? x : -x); u != 0; u /= 2)
{
if (u & 1)
r *= p;
p *= p;
}
return r;
}
else
{
// Пусть разбирается генератор кода.
return std::pow(b, double(x));
}
}
int main()
{
// Контекст константного выражения
constexpr double kilo = power(10.0, 3);
int n = 3;
// Не константное выражение, потому что n нельзя преобразовать в
// правостороннее значение в контексте константного выражения
// Эквивалентно std::pow(10.0, double(n))
double mucho = power(10.0, n);
std::cout << kilo << " " << mucho << "\n"; // (3)
}
Вывод:
1000 1000
Смотрите также
спецификатор constexpr(C++11)
|
указывает, что значение переменной или функции может быть вычислено во время компиляции |
спецификатор consteval (C++20)
|
указывает, что функция является немедленной функцией, то есть каждый вызов функции должен оцениваться константно |
спецификатор constinit (C++20)
|
утверждает, что переменная имеет статическую инициализацию, то есть инициализация нулём и константная инициализация |