Is this C++11 program ill-formed?
typedef void& rv;
int main() {}
I couldn't find anything disallowing it in the standard (looked in 3.9.2 and 8.3.2).
Clang says "cannot form a reference to 'void'", gcc says "cannot declare reference to ‘void’"
I would have expected [dcl.ref]/5 to give such a restriction, if it were intended.
Are the implementations just "reading between the lines" because such a type can never be used in an object definition?
You can - by casting - but the compiler can't. A reference to a void sufferes from the same problem, by definition the data pointed to doesn't have a type, therefore it can't be referenced in any meaningful way. To reference it you - the programmer - need to cast it to another type, then you can have a typed reference to it.
A declarator that specifies the type “ reference to cv void ” is ill-formed. As a side tidbit of info, this rule has been taken advantage by the N3421 greater<> proposal (which was already accepted to be included into the future C++14 standard) by having void as the default template argument. B.
When using a void pointer, you're not allowed to dereference it; transposed to the case of references, that means you can't use the (always hypothetical) void reference. So
reference to void has a useful property of being used as a generic reference argument in a constructor. So you can have Foo a(anyReference) and it could internally convert it to a void pointer. It in turn allows you to pass references and the constructor can take care of casting it to a pointer for you.
Quoting from the C++11 standard (emphasis mine):
8.3.2 References
1 [...] A declarator that specifies the type “reference to cv void” is ill-formed.
As a side tidbit of info, this rule has been taken advantage by the N3421 greater<> proposal (which was already accepted to be included into the future C++14 standard) by having void as the default template argument.
B. The technique of using default template arguments and explicit specializations for
voidwas chosen for its non-intrusiveness.greater<void>isn't valid C++11 (it would attempt to form a reference tovoid, forbidden by 8.3.2 [dcl.ref]/1). Additionally, while users are permitted to specialize Standard Library machinery (17.6.4.2.1 [namespace.std]/1), such specializations must involve user-defined types.
Maybe I'm just a bit more indulged into these mind games, but for the rationale of why this rule is enforced -- and I must state that this is just my own humble opinion -- consider the following code:
sizeof(double&); // Results in double's size
using foo_ref = foo&;
sizeof(foo_ref); // Results in foo's size
sizeof(void); // Error! void has no size!
sizeof(void&); // Error! Tries to get the size of void
Most importantly, keep in mind that references are just aliases of other objects, and you cannot have an object of type void.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With