В C23 добавлено ключевое слово constexpr, которое можно использовать для определения объектов как констант времени компиляции вместо перечислений или макросов. Например:
constexpr int x = 10;
constexpr int y = x+10; // Valid
switch (some_var) {
case y: // Valid
// ...
}
static int z = y; // Valid
Раньше только целочисленные константы (sizeof() или enum или литеральные значения, такие как 10) или адреса глобальных/static объектов можно было рассматривать как константы времени компиляции/трансляции, и во время компиляции над ними можно было выполнять несколько арифметических операций.
Есть ли какие-либо новые операции и типы, которые можно обрабатывать в выражении constexpr в C23? Каковы ограничения?





constexpr можно использовать для определения составного литерала:
Составной литерал со спецификатором класса хранения constexpr является составной литеральной константой. Составная литеральная константа — это постоянное выражение с типом и значением безымянного объекта.
До C23 не было поддержки составных литералов с константой времени компиляции (или даже static), даже если все их члены были константами времени компиляции:
static int x = (int){0}; // Non-portable
static int x = (constexpr int){0}; // Valid C23
struct и unionНачиная со структуры или константы объединения, оператор доступа к члену
.может использоваться для формирования именованной константы [...].
constexpr можно комбинировать с struct или union для создания объекта константы времени компиляции. Члены могут быть прочитаны во время компиляции:
constexpr struct {
int x;
} s = {10};
static int x = s.x; // Valid
Однако это не позволяет каламбура во время компиляции:
Если оператор доступа к члену
.обращается к члену константы объединения, доступный член должен быть тем же самым, что и член, который инициализируется инициализатором константы объединения.
Невозможно получить доступ к значению любого члена массива во время компиляции:
Операторы индекса массива
[]и доступа к члену->, унарные операторы адреса&и косвенности*, а также приведения указателей могут использоваться при создании адресной константы, но доступ к значению объекта с помощью этих операторов невозможен. .
Но эти операторы можно использовать для генерации адреса одного из членов массива в качестве константы времени компиляции.
Функции constexpr в стиле C++ не поддерживаются. Таким образом, в выражении constexpr нельзя использовать вызов функции.
Константные выражения не должны содержать операторы присваивания, увеличения, уменьшения, вызова функции или запятую, за исключением случаев, когда они содержатся в подвыражении, которое не оценивается.