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(), whereTis a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified)voidtype, 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
voidtypes 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.