reinterpret_cast on rvalues

449 views
Skip to first unread message

stackm...@hotmail.com

unread,
Feb 18, 2013, 9:02:49 AM2/18/13
to std-pr...@isocpp.org
I see no reason to disallow stuff like this:
auto x = reinterpret_cast<float>(42);
Currently one has to write stuff like this:
auto const x = rvalue;
auto y = *reinterpret_cast<float const*>(x);

Am I missing something?

Nicol Bolas

unread,
Feb 18, 2013, 5:47:06 PM2/18/13
to std-pr...@isocpp.org

Yes. That the latter is undefined behavior. In order for the specification to specify the behavior of `reinterpret_cast<float>`, it has to actually define what that means. And they don't want to, for many obvious reasons (like allowing implementations the latitude to define integers however they want, etc).

Sebastian Gesemann

unread,
Feb 19, 2013, 7:54:30 AM2/19/13
to std-pr...@isocpp.org
On Mon, Feb 18, 2013 at 3:02 PM, <stackm...@hotmail.com> wrote:
> I see no reason to disallow stuff like this:
> auto x = reinterpret_cast<float>(42);
> Currently one has to write stuff like this:
> auto const x = rvalue;
> auto y = *reinterpret_cast<float const*>(x);

The last fragment invokes undefined behaviour (violated aliasing rule).

I guess you want reinterpret_cast<T>(expr) for a scalar type T to be
equivalent to

template<class T, class U
,class = typename std::enable_if<
std::is_scalar<T>::value &&
std::is_scalar<U>::value &&
sizeof(T)==sizeof(U)
>::type
>
T reinterpret_value(U x)
{
T result;
std::memcpy(&result,&x,sizeof result);
return result;
}

reinterpret_cast already does something like this but only for the
cases where T and U are both pointer types or one is a pointer type
and the other is an integer type. In addition, reinterpret_cast can
deal with references in the following way: reinterpret_cast<T&>(x) ===
*reinterpret_cast<T*>(&x). I guess you could argue that the
restriction to pointer and integer types is artificial and that there
is no good reason against generalizing this to scalar types like
above.

I'm not sure right now, though, whether reinterpret_cast cares for the
"size(T)==size(U)" constraint. The only requirement I can recall in
this respect is that a roundtrip from pointer to integer and back
again actually compiles, that you can be sure that the original
pointer value is restored. This would require an integer type that is
at least as large as the original pointer type. But I'd have to check
this again.

Cheers!
SG

Johannes Schaub

unread,
Feb 20, 2013, 6:22:13 PM2/20/13
to std-pr...@isocpp.org


On Monday, February 18, 2013 3:02:49 PM UTC+1, stackm...@hotmail.com wrote:
I see no reason to disallow stuff like this:
auto x = reinterpret_cast<float>(42);
Currently one has to write stuff like this:
auto const x = rvalue;
auto y = *reinterpret_cast<float const*>(x);


That looks to me like a value cast of 42 to float, but would actually be a reinterpreting cast. In the cases where you give a prvalue or cast to a non-reference type, currently reinterpret_cast only does value casts, and never directly reinterprets object representations with certain types. 

So IMO this would be very confusing. You can do all that in one single line anyway (and earn UB)

    auto y = reinterpret_cast<const float&>((const int&)42);

Reply all
Reply to author
Forward
0 new messages