On Saturday, 2 July 2016 at 15:15:39 UTC, Guillaume Boucher wrote:
U opCast(U, T)(T payload)
{
import std.traits;
enum Tsizeof = is(T==bool) ? 0 : T.sizeof;
enum Usizeof = is(U==bool) ? 0 : U.sizeof;
enum noCheck = isUnsigned!T == isUnsigned!U && Tsizeof
<= Usizeof ||
isUnsigned!T && Tsizeof < Usizeof;
enum checkPayload = !isUnsigned!T && isUnsigned!U;
enum checkResult = isUnsigned!T && !isUnsigned!U;
static if (checkResult)
{
static assert(U.sizeof <= T.sizeof); // I
don't understand this
}
if (!checkPayload || payload >= 0)
{
auto result = cast(U) payload;
if (noCheck || result == payload &&
(!checkResult || result >= 0))
return result;
}
return hook!U(payload);
}
I got to something similar (probably with some typos), assuming
.sizeof exists:
U opCast(U, T)(T payload)
{
import std.traits;
enum unsigned_to_signed = isUnsigned!T && !isUnsigned!U;
enum signed_to_unsigned = !isUnsigned!T && isUnsigned!U;
enum maybe_to_smaller = T.sizeof >= U.sizeof;
enum to_smaller = T.sizeof > U.sizeof;
static assert( !unsigned_to_signed || maybe_to_smaller);
if( !signed_to_unsigned || to_smaller || payload >= 0 )
{
auto result = cast(U) payload;
if (result == payload && !( unsigned_to_signed && result
< 0))
return result;
}
return hook!U(payload);
}