Spec-Zone.ru › C++

static_assert объявление (начиная с C++11)

Выполняет проверку утверждений во время компиляции.

Синтаксис

static_assert( bool-constexpr , unevaluated-string ) (1)
static_assert( bool-constexpr ) (2) (начиная с C++17)
static_assert( bool-constexpr , constant-expression ) (3) (начиная с C++26)

Объявляет статическое утверждение. Если утверждение не выполняется, программа некорректна; может быть выдано диагностическое сообщение об ошибке.

1) Статическое утверждение с фиксированным сообщением об ошибке.
2) Статическое утверждение без сообщения об ошибке.
3) Статическое утверждение с сообщением об ошибке, сформированным пользователем.
Этот синтаксис может быть выбран, только если синтаксис (1) не подходит.

Пояснение

bool-constexpr -

контекстно преобразуемое константное выражение типа bool. Встроенные преобразования не допускаются, за исключением не сужающих целочисленных преобразований в bool.

(до C++23)

выражение, контекстно преобразуемое в bool, причём это преобразование является константным выражением

(начиная с C++23)
unevaluated-string - невычисляемый строковый литерал, который будет использован в качестве сообщения об ошибке
constant-expression - константное выражение msg, удовлетворяющее всем следующим условиям:
  • msg.size() неявно преобразуется в std::size_t.
  • msg.data() неявно преобразуется в constchar*.

Объявление static_assert может находиться в пространстве имён и в блочной области видимости (как объявление блока), а также внутри тела класса (как объявление-член).

Если bool-constexpr корректно и вычисляется в значение true либо вычисляется в контексте определения шаблона, а сам шаблон не инстанцирован, это объявление не оказывает никакого эффекта. В противном случае возникает ошибка компиляции, а предоставленное пользователем сообщение, если оно есть, включается в диагностическое сообщение.

Текст сообщения, предоставленного пользователем, определяется следующим образом:

  • Если сообщение соответствует синтаксическим требованиям к unevaluated-string, текстом сообщения является текст unevaluated-string.
  • В противном случае заданы следующие значения:
  • Пусть msg обозначает значение constant-expression.
  • Пусть len обозначает значение msg.size(), которое должно быть преобразованным константным выражением типа std::size_t.
  • Пусть ptr обозначает выражение msg.data(), неявно преобразованное в constchar*. ptr должно быть основным константным выражением.
Текст сообщения образуется последовательностью из len кодовых единиц, начиная с ptr, в обычной кодировке литералов. Для каждого целого числа i в [0, len) значение ptr[i] должно быть целочисленным константным выражением.
(начиная с C++26)

Примечания

Стандарт не требует от компилятора выводить текст сообщения об ошибке дословно, хотя компиляторы обычно делают это, насколько возможно.

Поскольку сообщение об ошибке должно быть строковым литералом, оно не может содержать динамическую информацию или даже константное выражение, которое само не является строковым литералом. В частности, оно не может содержать имя аргумента типа шаблона.

(до C++26)
Макрос проверки поддержки возможностей Значение Стандарт Возможность
__cpp_static_assert 200410L (C++11) static_assert (синтаксис (1))
201411L (C++17) static_assert с одним аргументом (синтаксис (2))
202306L (C++26) Сообщения об ошибках, формируемые пользователем (синтаксис (3))

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

static_assert

Пример

#include <format>
#include <type_traits>

static_assert(03301 == 1729); // since C++17 the message string is optional

template<class T>
void swap(T& a, T& b) noexcept
{
    static_assert(std::is_copy_constructible_v<T>,
                  "Swap requires copying");
    static_assert(std::is_nothrow_copy_constructible_v<T> &&
                  std::is_nothrow_copy_assignable_v<T>,
                  "Swap requires nothrow copy/assign");
    auto c = b;
    b = a;
    a = c;
}

template<class T>
struct data_structure
{
    static_assert(std::is_default_constructible_v<T>,
                  "Data structure requires default-constructible elements");
};

template<class>
constexpr bool dependent_false = false; // workaround before CWG2518/P2593R1

template<class T>
struct bad_type
{
    static_assert(dependent_false<T>, "error on instantiation, workaround");
    static_assert(false, "error on instantiation"); // OK because of CWG2518/P2593R1
};

struct no_copy
{
    no_copy(const no_copy&) = delete;
    no_copy() = default;
};

struct no_default
{
    no_default() = delete;
};

#if __cpp_static_assert >= 202306L
// Not real C++ yet (std::format should be constexpr to work):
static_assert(sizeof(int) == 4, std::format("Expected 4, got {}", sizeof(int)));
#endif

int main()
{
    int a, b;
    swap(a, b);
    
    no_copy nc_a, nc_b;
    swap(nc_a, nc_b); // 1
    
    [[maybe_unused]] data_structure<int> ds_ok;
    [[maybe_unused]] data_structure<no_default> ds_error; // 2
}

Возможный вывод:

1: error: static assertion failed: Swap requires copying
2: error: static assertion failed: Data structure requires default-constructible elements
3: error: static assertion failed: Expected 4, got 2

Отчёты об исправлении дефектов

Следующие отчёты об исправлении дефектов, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применён к Опубликованное поведение Корректное поведение
CWG 2039 C++11 требование константности распространяется только на выражение до преобразования преобразование также должно быть
допустимо в константном выражении
CWG 2518
(P2593R1)
C++11 неинстанцированный static_assert(false, ""); был некорректен сделан корректным

Ссылки

  • Стандарт C++23 (ISO/IEC 14882:2024):
    • 9.1 Преамбула [dcl.pre] (стр. 10)
  • Стандарт C++20 (ISO/IEC 14882:2020):
    • 9.1 Преамбула [dcl.pre] (стр. 6)
  • Стандарт C++17 (ISO/IEC 14882:2017):
    • 10 Объявления [dcl.dcl] (стр. 6)
  • Стандарт C++14 (ISO/IEC 14882:2014):
    • 7 Объявления [dcl.dcl] (стр. 4)
  • Стандарт C++11 (ISO/IEC 14882:2011):
    • 7 Объявления [dcl.dcl] (стр. 4)

См. также

#error
выводит заданное сообщение об ошибке и делает программу некорректной
(директива препроцессора)
assert
прерывает выполнение программы, если заданное пользователем условие не true. Может быть отключён в сборках для выпуска.
(функциональный макрос)
инструкция contract_assert (C++26) проверяет внутреннее условие во время выполнения
enable_if
(C++11)
условно исключает перегрузку функции или специализацию шаблона из разрешения перегрузки
(шаблон класса)
Характеристики типов (C++11) определяют интерфейсы на основе шаблонов для запроса свойств типов во время компиляции
Документация по C для статического утверждения

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/static_assert

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API