consteval спецификатор (начиная с C++20)
-
consteval— указывает, что функция является немедленной функцией, то есть каждый вызов функции должен возвращать константу времени компиляции
Объяснение
Спецификатор consteval объявляет функцию или шаблон функции немедленной функцией, то есть каждый потенциально вычисляемый вызов функции должен (непосредственно или косвенно) возвращать константное выражение времени компиляции.
Немедленная функция является функцией constexpr и должна соответствовать применимым к ней требованиям. Как и constexpr, спецификатор consteval подразумевает inline. Однако его нельзя применять к деструкторам, функциям выделения памяти или функциям освобождения памяти.
Объявление функции или шаблона функции со спецификатором consteval не может также содержать спецификатор constexpr, а все повторные объявления этой функции или шаблона функции также должны содержать спецификатор consteval.
Потенциально вычисляемый вызов немедленной функции, чья самая внутренняя область видимости, не являющаяся блочной, не является областью видимости параметров функции немедленной функции или истинной ветвью оператора if consteval(начиная с C++23), должен возвращать константное выражение; такой вызов называется немедленным вызовом.
consteval int sqr(int n)
{
return n*n;
}
constexpr int r = sqr(100); // OK
int x = 100;
int r2 = sqr(x); // Error: Call does not produce a constant
consteval int sqrsqr(int n)
{
return sqr(sqr(n)); // Not a constant expression at this point, but OK
}
constexpr int dblsqr(int n)
{
return 2 * sqr(n); // Error: Enclosing function is not consteval
// and sqr(n) is not a constant
}
Немедленную функцию можно именовать только внутри подвыражения немедленного вызова или в контексте немедленной функции (то есть в контексте, упомянутом выше, где вызов немедленной функции не обязан быть константным выражением). Можно получить указатель или ссылку на немедленную функцию, но они не могут выйти за пределы вычисления константного выражения:
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(); // ill-formed: a pointer to an immediate function is
// not a permitted result of a constant expression
Примечания
| Макрос проверки поддержки функциональности | Значение | Стандарт | Функциональность |
|---|---|---|---|
__cpp_consteval | 201811L | (C++20) | Немедленные функции |
202211L |
(C++23) (DR20) | Распространение consteval вверх по цепочке |
Ключевые слова
Пример
#include <iostream>
// This function might be evaluated at compile-time, if the input
// is known at compile-time. Otherwise, it is executed at run-time.
constexpr unsigned factorial(unsigned n)
{
return n < 2 ? 1 : n * factorial(n - 1);
}
// With consteval we enforce that the function will be evaluated at compile-time.
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); // error: 'argc' is not a constant expression
}
Вывод:
24
См. также
спецификатор constexpr(C++11) | указывает, что значение переменной или функции может быть вычислено во время компиляции |
спецификатор constinit(C++20) | утверждает, что переменная имеет статическую инициализацию, то есть нулевую инициализацию и константную инициализацию |
| константное выражение | определяет выражение, которое может быть вычислено во время компиляции |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/consteval