July 31, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On 7/30/18 2:30 PM, 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
>
OK, so one thing to learn in D, you can't hijack stuff. When you override a function, you have to override ALL the overloads.
What you have done is defined opAssign as ONLY accepting a float, and then disabling any calls to it.
This is obfuscated somewhat by the fact that 3 can be a float as well. So even if you didn't disable the opAssign(float), it would still call that function.
You can get around it by defining a forwarding function for the overloads you want to let through:
@disable void opAssign(float);
auto opAssign(int x) { return a.opAssign(x); }
-Steve
|
August 01, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 31 July 2018 at 20:40:25 UTC, Steven Schveighoffer wrote:
> OK, so one thing to learn in D, you can't hijack stuff. When you override a function, you have to override ALL the overloads.
I could have sworn I tested this before I wrote that it's a bug:
struct A {
void fun(int) {}
}
struct B {
A a;
alias a this;
@disable void fun(float);
}
void main() {
B b;
b.fun(3);
}
I was surprised to see it work, as I also thought it'd be a hijacking issue. Turns out, it doesn't actually work. I must have made a typo when I tried it. Ah well.
--
Simen
|
August 02, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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; } )); } |
Copyright © 1999-2021 by the D Language Foundation