I know that (void)0
is a no-op in C/C++.
However, when I was looking through the code in <cassert>
, I saw void (0)
.
I guess it’s something like int (0)
or int{0}
.
I also tried void{}
and it works.
It seems that this is a zero-initialization for void
.
But void
is an incomplete type, how come the compiler doesn’t complain? (g++-14 -std=c++23 -Wall
)
6
Both void(0)
and void{}
are function-style explicit type conversion expressions in the standard, and the semantics are defined as follows,
If the initializer is a parenthesized single expression, the type conversion expression is equivalent to the corresponding cast expression. Otherwise, if the type is
cv
void
and the initializer is () or {} (after pack expansion, if any), the expression is a prvalue of typevoid
that performs no initialization.
For void(0)
, the first sentence applies, and the expression is semantically equivalent to (void)0
, which you already know about. To further expand, this is equivalent to static_cast<void>(0)
where the standard makes a special case for cv
void
in expr.static.cast. For void{}
, the second sentence comes into play, and the standard explicitly specifies that no initialization is performed. In either case, there is no “initialization of incomplete type” involved, and that explains why the compiler doesn’t complain.
1
When you write T(E)
in C++ where T
is a type and E
a single expression, then that is called a functional-style cast expression and exactly equivalent to the old-style cast expression (T)E
in terms of semantics.
So void(0)
is exactly equivalent to (void)0
.
(There are some parsing differences in terms of operator precedence and what the grammar permits T
to contain exactly.)