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