While arguing with someone over the suggestion he made in the comment thread of this answer, I came across some code that gcc4.8 and VS2013 refuse to compile but clang happily accepts it and displays the correct result.
#include <iostream>
int main()
{
int i{ 5 };
void* v = &i;
std::cout << reinterpret_cast<int&>(*v) << std::endl;
}
Live demo. Both GCC and VC fail with the error I was expecting, complaining that the code attempts to dereference a void* within the reinterpret_cast. So I decided to look this up in the standard. From N3797, §5.2.10/11 [expr.reinterpret.cast]
A glvalue expression of type
T1can be cast to the type “reference toT2” if an expression of type “pointer toT1” can be explicitly converted to the type “pointer toT2” using areinterpret_cast. The result refers to the same object as the source glvalue, but with the specified type. [ Note: That is, for lvalues, a reference castreinterpret_cast<T&>(x)has the same effect as the conversion*reinterpret_cast<T*>(&x)with the built-in&and*operators (and similarly forreinterpret_cast<T&&>(x)). —end note ] No temporary is created, no copy is made, and constructors (12.1) or conversion functions (12.3) are not called.
In this case T1 is void and T2 is int, and a void* can be converted to int* using reinterpret_cast. So all requirements are met.
According to the note, reinterpret_cast<int&>(*v) has the same effect as *reinterpret_cast<int*>(&(*v)), which, by my reckoning, is the same as *reinterpret_cast<int*>(v).
So is this a GCC and VC bug, or are clang and I misinterpreting this somehow?
An expression of type void is allowed as a mostly just syntactical device in a return statement, and also you can cast an expression to void, but that's all: there are no glvalues of type void, an expression of type void does not refer to memory. Thus the quoted passage from the standard, starting with a glvalue, does not apply. Thus, clang is wrong.
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