Disabling opAssign in a type disabled all the opAssigns of an aliased type?

Simen Kjærås simen.kjaras at gmail.com
Mon Jul 30 20:54:28 UTC 2018


On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote:
> Is this a bug?
>
> If not is there a workaround?
>
> I would like for the alias this to function as a normal A type 
> unless B specifically disables certain features, but it seems 
> weird that disabling one opAssign disables all of them inside 
> the aliases type but not in the aliasing type?
>
>
> struct A {
>     void opAssign(int) {}
> }
> struct B {
>     A a;
>     alias a this;
>     @disable void opAssign(float);
> }
>
> void main() {
>     B b;
>     b = 3;
> }
>
> Error: function `onlineapp.B.opAssign` is not callable because 
> it is annotated with @disable


The workaround is to not disable opAssign. :p

Since this does work for other member functions that opAssign, 
I'm gonna say it's a bug - please file it in Bugzilla.

A perhaps better workaround than the above is to wrap A's 
opAssigns. Sadly, this can't be done with template mixins, since 
they don't overload with non-mixins. It can be done with string 
mixins, however. It's also possible to encapsulate all this in a 
nice little template:

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

string wrap(T, string methodName)() {
     enum targetName = __traits(getAliasThis, T)[0];
     return `import std.traits : Parameters, ReturnType;
     static foreach (e; __traits(getOverloads, 
typeof(`~targetName~`), "`~methodName~`"))
         static if (!is(typeof({static assert(__traits(isDisabled, 
getOverload!(typeof(this), "`~methodName~`", Parameters!e)));})))
             ReturnType!e `~methodName~`(Parameters!e args) {
                 return __traits(getMember, `~targetName~`, 
"`~methodName~`")(args);
             }`;
}

template getOverload(T, string name, Args...) {
     import std.traits : Parameters;
     import std.meta : AliasSeq;
     template impl(overloads...) {
         static if (overloads.length == 0) {
             alias impl = AliasSeq!();
         } else static if (is(Parameters!(overloads[0]) == Args)) {
             alias impl = overloads[0];
         } else {
             alias impl = impl!(overloads[1..$]);
         }
     }
     alias getOverload = impl!(__traits(getOverloads, T, name));
}

unittest {
     B b;
     b = 3;
     static assert(!__traits(compiles, b = 3f));
}

And that's enough magic for me for one night.

--
   Simen



More information about the Digitalmars-d-learn mailing list