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
void
was 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