Namespaces
Variants

consteval specifier (since C++20)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous
  • 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 вверх

Ключевые слова

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 которое может быть вычислено во время компиляции