Thread overview | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 30, 2018 Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
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 Cheers, - Ali |
July 30, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | 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
>
> Cheers,
> - Ali
What happens if you omit the @disable line?
|
July 30, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On Monday, 30 July 2018 at 18:47:06 UTC, Alex wrote:
> 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
>>
>> Cheers,
>> - Ali
>
> What happens if you omit the @disable line?
Compiles ok then.
|
July 30, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On Monday, 30 July 2018 at 19:33:45 UTC, aliak wrote:
> On Monday, 30 July 2018 at 18:47:06 UTC, Alex wrote:
>> On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote:
>>> [...]
>>
>> What happens if you omit the @disable line?
>
> Compiles ok then.
So... is this a valid workaround? ;)
|
July 30, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On Monday, 30 July 2018 at 20:20:15 UTC, Alex wrote:
> On Monday, 30 July 2018 at 19:33:45 UTC, aliak wrote:
>> On Monday, 30 July 2018 at 18:47:06 UTC, Alex wrote:
>>> On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote:
>>>> [...]
>>>
>>> What happens if you omit the @disable line?
>>
>> Compiles ok then.
>
> So... is this a valid workaround? ;)
Hehe. Unfortunately not. It's for a proxy type that I need to disallow assignment to. But the proxy type uses alias to a T. So if T has a custom opAssign then bye bye functionality.
|
July 30, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On Monday, 30 July 2018 at 20:38:33 UTC, aliak wrote: > On Monday, 30 July 2018 at 20:20:15 UTC, Alex wrote: >> On Monday, 30 July 2018 at 19:33:45 UTC, aliak wrote: >>> On Monday, 30 July 2018 at 18:47:06 UTC, Alex wrote: >>>> On Monday, 30 July 2018 at 18:30:16 UTC, aliak wrote: >>>>> [...] >>>> >>>> What happens if you omit the @disable line? >>> >>> Compiles ok then. >> >> So... is this a valid workaround? ;) > > Hehe. Unfortunately not. It's for a proxy type that I need to disallow assignment to. But the proxy type uses alias to a T. So if T has a custom opAssign then bye bye functionality. The actual code is here if you're curious: https://github.com/aliak00/optional/pull/16/commits/93d51d790d313be3b108df2bd8b3699adc898bd0 Right now I've only: @disable this(); // Do not allow user creation of a Dispatcher @disable this(this) {} // Do not allow blitting either But I also want to @disable void opAssign(U)(Dispatcher!U) So that you can't reassign to the Dispatcher (i.e. proxy type) But if I do that then the opAssigns in the Optional!T cease functioning. |
July 30, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | 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
|
July 30, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | On Monday, 30 July 2018 at 20:54:28 UTC, Simen Kjærås wrote: > 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 Heheh .... Amazing! In today's episode of extreme D (why is that not a thing?), we give you a "nice little template" :p https://issues.dlang.org/show_bug.cgi?id=19130 Would it take much to fix it up to use with templated opAssigns as well? I tried for a bit and got stuck with trying to get parameters and now I'm giving up for the time being. struct A { void opAssign(int) {} void opAssign()(float) {} } struct B(T) { A a; alias a this; @disable void opAssign(U)(B!U); import std.traits : Parameters, ReturnType; static foreach (t; __traits(getOverloads, A, "opAssign", true)) { static if (is(typeof(t.stringof))) { pragma(msg, t.stringof, " - ", Parameters!t); } else { pragma(msg, typeof(t), " - ", Parameters!t); } } } The Parameters!t of the template overloads all come out as "int" but only if there's the non-template opAssign(int) in A. If you remove that then you get errors. So something is fishy. Also I realized that it's just 2 opAssigns in the aliased Optional!T type for my specific use case so maybe, err... copy pasta them in. Cheers, - Ali |
July 31, 2018 Re: Disabling opAssign in a type disabled all the opAssigns of an aliased type? | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | 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 |
July 31, 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:
> auto opAssign(T...)(T args)
Admittedly, one rarely uses multi-argument opAssign, but for those rare occasions... :p
--
Simen
|
Copyright © 1999-2021 by the D Language Foundation