On Tuesday, 31 July 2018 at 07:01:33 UTC, Simen Kjærås wrote:
On Monday, 30 July 2018 at 23:41:09 UTC, aliak wrote:
https://issues.dlang.org/show_bug.cgi?id=19130

Beautiful. :)

Would it take much to fix it up to use with templated opAssigns as well?

I spent half an hour doing silly things, then I came up with this:

struct A {
    void opAssign(int) {}
    void opAssign(float) {}
    void opAssign(T)(T t) if (is(T == string)) {}
}
struct B {
    A a;
    alias a this;
    @disable void opAssign(float);
    mixin(wrap!(B, "opAssign"));
    auto opAssign(T...)(T args)
    if (__traits(compiles, a.opAssign(args)))
    {
        // Look ma, no magic!
        return a.opAssign(args);
    }
}
unittest {
    B b;
    b = "Foo!";
}

(Remaining code as in my last post)

Yeah, it really is that simple, since specific overloads are tried before templates.

--
  Simen

Oh nice! So you don't even need all that mixin magic and can get away with:

struct A {
    void opAssign(int) {}
    @disable void opAssign(float) {}
    void opAssign(T)(T t) if (is(T == string)) {}
}

struct B(T) {
    A a;
    alias a this;
    @disable void opAssign(B!T);
    mixin(wrap!(B, "opAssign"));
}

string wrap(T, string methodName)() {
    enum targetName = __traits(getAliasThis, T)[0];
    return `auto `~methodName~`(T...)(T args)
if (__traits(compiles, `~targetName~`.`~methodName~`(args))) {
        return `~targetName~`.`~methodName~`(args);
    }`;
}

void main() {
    B!int b;
    b = 3;
    b = "hello";
    static assert(!__traits(compiles, { b = 3f; } ));
    static assert(!__traits(compiles, { b = b; } ));
}




Reply via email to