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

2018-08-02 Thread aliak via Digitalmars-d-learn

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; } ));
}






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

2018-08-01 Thread Simen Kjærås via Digitalmars-d-learn
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


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

2018-07-31 Thread Steven Schveighoffer via Digitalmars-d-learn

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


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

2018-07-31 Thread Simen Kjærås via Digitalmars-d-learn

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


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

2018-07-31 Thread Simen Kjærås via Digitalmars-d-learn

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


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

2018-07-30 Thread aliak via Digitalmars-d-learn

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




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

2018-07-30 Thread Simen Kjærås via Digitalmars-d-learn

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



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

2018-07-30 Thread aliak via Digitalmars-d-learn

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.




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

2018-07-30 Thread aliak via Digitalmars-d-learn

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.


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

2018-07-30 Thread Alex via Digitalmars-d-learn

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? ;)


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

2018-07-30 Thread aliak via Digitalmars-d-learn

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.


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

2018-07-30 Thread Alex via Digitalmars-d-learn

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?


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

2018-07-30 Thread aliak via Digitalmars-d-learn

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