Basically, I\'d like to know why the compiler rejects ptr2
declaration:
int main() {
// this one works
decltype(void())* ptr1;
// t
[expr.type.conv]
2 The expression
T()
, whereT
is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified)void
type, creates a prvalue of the specified type, whose value is that produced by value-initializing (8.5) an object of typeT
; no initialization is done for thevoid()
case. [...]
N.B. void
is a simple-type-specifier.
3 Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (8.5.4) with the specified braced-init-list, and its value is that temporary object as a prvalue.
Thanks to Keith Thompson for pointing out that a temporary object is created in /3, whereas a value is created in /2.
When we take a look at [basic.types]/5
Incompletely-defined object types and the
void
types are incomplete types (3.9.1). Objects shall not be defined to have an incomplete type.
It now becomes clear that void{}
is not allowed as it would create a (temporary) object. void()
however "only" creates a (pr)value. I don't think there's a difference in the implementation (behaviour) for those two cases, but different language rules apply to them. One of those rules forbids creation of an object of type void
, hence the error.
Ad decltype(void())
: decltype(e)
takes an expression e
. In [dcl.type.simple]/4, the applicable definition of decltype(e)
is:
otherwise,
decltype(e)
is the type ofe
(as void()
yields a prvalue and is not an id-expression).
Therefore, decltype(void())
yields void
.