C23 added a keyword constexpr
which can be used to define objects as compile-time constants instead of enumerations or macros. For example:
constexpr int x = 10;
constexpr int y = x+10; // Valid
switch (some_var) {
case y: // Valid
// ...
}
static int z = y; // Valid
Previously only integer constants (sizeof()
or enum
or literal values such as 10
) or addresses of global/static
objects could be treated as compile/translation-time constants and a handful of arithmetic operations could be performed on them at compile-time.
Are there any new operations and types can be handled in a constexpr
expression in C23? What are the limitations?
constexpr
can be used to qualify compound literal:
A compound literal with storage-class specifier constexpr is a compound literal constant. A compound literal constant is a constant expression with the type and value of the unnamed object.
Before C23 there was no support for compile-time constant (Or even static
) compound literals even if all their members were compile-time constant:
static int x = (int){0}; // Non-portable
static int x = (constexpr int){0}; // Valid C23
struct
and union
Starting from a structure or union constant, the member-access
.
operator may be used to form a named constant [...].
constexpr
can be combined with a struct
or union
to create a compile-time constant object. The members may be read at compile time:
constexpr struct {
int x;
} s = {10};
static int x = s.x; // Valid
This does not permit compile-time type-punning though:
If the member-access operator
.
accesses a member of a union constant, the accessed member shall be the same as the member that is initialized by the union constant's initializer.
There is no way to access the value of any array member at compile time:
The array-subscript
[]
and member-access->
operator, the address&
and indirection*
unary operators, and pointer casts may be used in the creation of an address constant, but the value of an object shall not be accessed by use of these operators.
But those operators can be used to generate an address of one of the array members as a compile-time constant.
C++-style constexpr
functions are not supported. As such no function call can be used in a constexpr
expression.
Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.