Thread overview
[Issue 20117] std.typecons.Typedef has opCmp when base type does not
Aug 09, 2019
Simen Kjaeraas
Aug 09, 2019
Simen Kjaeraas
Aug 09, 2019
Atila Neves
Aug 09, 2019
Simen Kjaeraas
Jan 09, 2020
berni44
Dec 17, 2022
Iain Buclaw
August 09, 2019
https://issues.dlang.org/show_bug.cgi?id=20117

Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras@gmail.com

--- Comment #1 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
This would perhaps more correctly be filed as 'int does not have opCmp'. Since int does support the <, <=, >=, > operators it kinda, sorta has opCmp, but no member by that name. That's not really an option for Typedef, as it's not a magic type like int. At the same time, we absolutely expect MyInt.init < MyInt.init to compile.

There may be a good argument for adding opCmp and friends to built-in types to make generic code more generic, but removing them from Typedef is no solution.

--
August 09, 2019
https://issues.dlang.org/show_bug.cgi?id=20117

--- Comment #2 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
Alternatively, Typedef should contain only a single member and use aliases for the rest. Something like this:

struct Typedef(T, T init = T.init, string cookie=null) {
    // Renaming the current Typedef:
    TypedefImpl!(T, init, cookie) _payload;
    alias _payload this;
    static foreach (e; __traits(allMembers, T))
        mixin("alias "~e~" = _payload."~e~";");
}

--
August 09, 2019
https://issues.dlang.org/show_bug.cgi?id=20117

--- Comment #3 from Atila Neves <atila.neves@gmail.com> ---
But `int` *doesn't* have `opCmp`. I found this by trying to wrap a generic type for Python and implementing the comparison. std.typecons.Typedef completely broke things and I have to special-case for it, because `hasMember!(Typedef, "opCmp")` returns true, but then one can't actually forward to it because it doesn't actually exist.

Incidentally, the reason the bug happens is because `Typedef` uses `Proxy` in its implementation, and `Proxy` defines `opCmp`.

--
August 09, 2019
https://issues.dlang.org/show_bug.cgi?id=20117

--- Comment #4 from Simen Kjaeraas <simen.kjaras@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.

--
January 09, 2020
https://issues.dlang.org/show_bug.cgi?id=20117

berni44 <bugzilla@d-ecke.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@d-ecke.de
           Hardware|x86_64                      |All
                 OS|Linux                       |All

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=20117

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P3

--