Спецификатор consteval
(начиная с C++20)
consteval
- указывает, что функция является немедленной функцией, то есть каждый вызов функции должен создавать константу времени компиляции
Содержание |
[править] Объяснение
Спецификатор consteval
объявляет функцию или шаблон функции как немедленную функцию, то есть каждый потенциально вычисляемый вызов (т.е. вызов из неоцененного контекста) функции должен (прямо или косвенно) создавать константное выражение времени компиляции.
Немедленная функция является функцией constexpr и должна соответствовать требованиям, применимым к функциям constexpr или конструкторам 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)); // Не постоянное выражение в этой точке, но ОК } 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++20) | Заставляет 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)
|
утверждает, что переменная имеет статическую инициализацию, то есть инициализация нулём и константная инициализация |
константное выражение | определяет выражение, которое можно оценить во время компиляции |