Пространства имён
Варианты
Действия

Спецификатор consteval (начиная с C++20)

Материал из cppreference.com
< cpp‎ | language
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
if
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений (до C++17*)
Спецификатор noexcept (C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype (C++11)
auto (C++11)
alignas (C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr (C++11)
Определяемые пользователем (C++11)
Утилиты
Атрибуты (C++11)
Types
Объявление typedef
Объявление псевдонима типа (C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции класса
explicit (C++11)
static
Специальные функции-элементы
Шаблоны
Разное
 
Обьявления
Объявления
ссылка
указатель
массив
Block declarations
простое объявление
объявление структурных привязок (C++17)
объявление псевдонимов(C++11)
объявление псевдонимов пространств имён
using-declaration
директива using
объявление static_assert (C++11)
определение asm
объявление непрозрачного enum(C++11)
Другие объявления
определение пространств имён
объявление функции
объявление шаблона класса
объявление шаблона функции
явное инстанцирование шаблона(C++11)
явная специализация шаблона
спецификация связывания
объявление атрибута (C++11)
пустое объявление
 
  • 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 распространяться вверх

[править] Ключевые слова

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) утверждает, что переменная имеет статическую инициализацию, то есть инициализация нулём и константная инициализация[править]
константное выражение определяет выражение, которое можно оценить во время компиляции