[Issue 20117] std.typecons.Typedef has opCmp when base type does not

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Aug 9 11:37:22 UTC 2019


https://issues.dlang.org/show_bug.cgi?id=20117

--- Comment #4 from Simen Kjaeraas <simen.kjaras at gmail.com> ---
But `int` *is* comparable using <, <=, >=, and >, so any (non-built-in) type
pretending to be an int needs to have `opCmp`. What you're asking for is
basically to cripple `Typedef` because you need to write some workaround code.
Alternatively, you're asking for what I said in comment 2, but have elected to
ignore that.

Actually, even with my `alias this` solution in comment 2, you get two members:
`_payload`, and `opAssign`. The former we've defined, the latter the compiler
makes for us. `int` does not have `opAssign`, so we can't forward to that, thus
again causing possible issues. In fact, `int` doesn't have any members at all,
if you ask `__traits(allMembers)`. Thus, any member whatsoever in `Typedef!int`
could be problematic in generic code. I hope we can agree that `Typedef!int`
needs to have at least one member.

Actually, we can get rid of all fields by (ab)using `align` and some creative
casting:

template Typedef(T) {
    align ((T.sizeof + 1) & -2) // powers of 2 only
    struct Typedef {
        ref auto _payload() {
            import std.typecons : TypedefImpl = Typedef;
            return *cast(TypedefImpl!T*)&this;
        }
        alias _payload this;

        // alias all members of the wrapped type
        static if (__traits(compiles, __traits(allMembers, T)))
            static foreach (e; __traits(allMembers, T))
                mixin("alias _payload."~e~" "~e~";");
    }
}

This still leaves us with a single method (`_payload()`) that I haven't found a
way to get rid of yet. Also, it's hella ugly.

--


More information about the Digitalmars-d-bugs mailing list