consteval
specifier
(since C++20)
-
-
consteval- указывает, что функция является немедленной функцией , то есть каждый вызов функции должен давать константу времени компиляции
-
Содержание |
Объяснение
Спецификатор
consteval
объявляет функцию или шаблон функции как
непосредственную функцию
, то есть каждый
потенциально вычисляемый
вызов функции должен (прямо или косвенно) производить константное выражение времени компиляции
constant expression
.
Немедленная функция является
constexpr-функцией
, подчиняющейся соответствующим требованиям в зависимости от ситуации. Так же как и
constexpr
, спецификатор
consteval
подразумевает
inline
. Однако он не может применяться к деструкторам, функциям выделения памяти или функциям освобождения памяти.
Объявление функции или шаблона функции, указывающее
consteval
, не может также указывать
constexpr
, и любые переобъявления этой функции или шаблона функции также должны указывать
consteval
.
Вызов немедленной функции, который потенциально вычисляется и чья самая внутренняя неблочная область видимости не является областью видимости параметров функции немедленной функции или истинной ветвью оператора consteval if (начиная с C++23) , должен порождать константное выражение; такой вызов называется немедленным вызовом .
consteval int sqr(int n) { return n*n; } constexpr int r = sqr(100); // OK int x = 100; int r2 = sqr(x); // Ошибка: вызов не дает константу consteval int sqrsqr(int n) { return sqr(sqr(n)); // Не константное выражение в этой точке, но OK } constexpr int dblsqr(int n) { return 2 * sqr(n); // Ошибка: Окружающая функция не является consteval // и sqr(n) не является константой }
Идентификаторное выражение , обозначающее непосредственную функцию, может появляться только внутри подвыражения непосредственного вызова или в контексте непосредственной функции (т.е. в контексте, упомянутом выше, где вызов непосредственной функции не обязан быть константным выражением). Указатель или ссылка на непосредственную функцию может быть взята, но не может покидать вычисление константного выражения:
consteval int f() { return 42; } consteval auto g() { return &f; } consteval int h(int (*p)() = g()) { return p(); } constexpr int r = h(); // OK constexpr auto e = g(); // некорректно: указатель на немедленную функцию не // является допустимым результатом константного выражения
Примечания
| Макрос тестирования возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_consteval
|
201811L
|
(C++20) | Немедленные функции |
202211L
|
(C++23)
(DR20) |
Распространение consteval вверх |
Ключевые слова
Пример
#include <iostream> // Эта функция может быть вычислена во время компиляции, если входные данные // известны во время компиляции. В противном случае она выполняется во время выполнения. constexpr unsigned factorial(unsigned n) { return n < 2 ? 1 : n * factorial(n - 1); } // С помощью consteval мы обеспечиваем, что функция будет вычислена во время компиляции. consteval unsigned combination(unsigned m, unsigned n) { return factorial(n) / factorial(m) / factorial(n - m); } static_assert(factorial(6) == 720); static_assert(combination(4, 8) == 70); int main(int argc, const char*[]) { constexpr unsigned x{factorial(4)}; std::cout << x << '\n'; [[maybe_unused]] unsigned y = factorial(argc); // OK // unsigned z = combination(argc, 7); // ошибка: 'argc' не является константным выражением }
Вывод:
24
Смотрите также
constexpr
спецификатор
(C++11)
|
указывает, что значение переменной или функции может быть вычислено во время компиляции |
constinit
спецификатор
(C++20)
|
утверждает, что переменная имеет статическую инициализацию, т.е. zero initialization и constant initialization |
| constant expression | определяет expression которое может быть вычислено во время компиляции |