[OT] Checked opCast
Timon Gehr via Digitalmars-d
digitalmars-d at puremagic.com
Sat Jul 2 17:57:04 PDT 2016
On 02.07.2016 14:26, Andrei Alexandrescu wrote:
>
> How would you reshape this? It's important that the call to hook is
> physically at the end of the function and issued just in that place, and
> that the code does not do any redundant work.
>
> U hook(U, T)(T value) { return U.init; }
>
> U opCast(U, T)(T payload)
> {
> import std.traits;
> do
> {
> static if (!isUnsigned!T && isUnsigned!U &&
> T.sizeof <= U.sizeof)
> {
> if (payload < 0) break; // extra check needed
> }
> auto result = cast(U) payload;
> if (result != payload) break;
> static if (isUnsigned!T && !isUnsigned!U)
> {
> static assert(U.sizeof <= T.sizeof);
> if (result < 0) break;
> }
> return result;
> } while (0);
> return hook!U(payload);
> }
>
> void main()
> {
> opCast!short(42);
> }
>
>
> Thanks,
>
> Andrei
How do you decide what 'redundant work' is? Is this combination of
branches and type casts really particularly cheap to execute? Could
masking out the "sign bit" from the unsigned value before comparison be
faster? Also, isn't the result != payload check redundant if sizeof(U)
== sizeof(T)?
Anyway, this is the kind of optimization that compilers are supposed to
be good at, it should pick whatever procedure is optimal, not
necessarily the one specified. Personally, I'd just write something like:
U opCast(U,T)(T payload)if(...){
auto result = cast(U)payload;
if(result == payload && (result<0) == (payload<0))
return result;
return hook!U(payload);
}
More information about the Digitalmars-d
mailing list