Bug 5893 – Allow simple aliases for operator overloading
Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-04-26T13:04:00Z
Last change time
2013-02-06T08:55:06Z
Keywords
pull
Assigned to
nobody
Creator
schveiguy
Comments
Comment #0 by schveiguy — 2011-04-26T13:04:35Z
If you wish to use virtual operators in D classes, the current thinking is you would wrap a virtual function with a template function that handles the operator. This means you have to implement a template function, taking care to use the same arguments that the other function will require, and using the proper return type as well.
I thought of an alternative way to do this that makes wrapping virtual functions super-easy. However, the compiler rejects it (for a strange reason).
class C
{
void concatAssign(C other) { }
void concatAssign(int other) { } // to demonstrate overloading
template opOpAssign(string s) if (s == "~=") // line 6
{ alias concatAssign opOpAssign; }
}
void main()
{
auto c = new C;
c.opOpAssign!"~="(c); // works
c.opOpAssign!"~="(1); // works
c ~= 1; // line 15
}
testaliasvirt.d(6): Error: template testaliasvirt.C.opOpAssign(string s) if (s == "~=") is not a function template
testaliasvirt.d(15): Error: cannot append type int to type testaliasvirt.C
I think the compiler should accept this code. In fact, I thought the compiler just rewrote ~= to .opOpAssign!"~=". The error message seems to suggest it does some unnecessary checking to make sure it's a function template.
If it did work, this method provides not only a very efficient and backwards compatible way to do operators (no wrapper code is generated/called, no relying on inlining to make sure performance isn't hurt), but one could easily create a single mixin that forwarded all operators to the old style operators (if you didn't want to do it manually like I have). You don't even need to deal with forwarding parameters (the biggest pain of auto-wrapping functions)!
I can see this being of use for opDispatch as well.
Note that bug 4182 would have to be fixed for true backward compatibility (i.e. forwarding covariance with the virtual operators). But that technically is a separate issue, not a blocker.
Comment #1 by andrej.mitrovich — 2012-01-21T18:19:18Z
Hows this for a workaround:
import std.traits;
class C
{
void concatAssign(C other) { }
void concatAssign(int other) { }
auto ref opOpAssign(string s, T)(T t) if (s == "~")
{
static if (is(ReturnType!concatAssign == void))
concatAssign(t);
else
return concatAssign(t);
}
}
void main()
{
auto c = new C;
c.opOpAssign!"~"(c); // works
c.opOpAssign!"~"(1); // works
c ~= 1; // works
}
Comment #2 by timon.gehr — 2012-01-21T18:35:23Z
1. The static if in the function body is not required. You can return a void expression from a void function.
2. Here is what still does not work:
class C{
void concatAssign(C other) { }
void concatAssign(short other) { }
void concatAssign(short[] other) { }
auto ref opOpAssign(string s, T)(T t) if (s == "~"){
return concatAssign(t);
}
}
void main()
{
auto c = new C;
c.opOpAssign!"~"(c); // works
c.opOpAssign!"~"(1); // no go
c ~= 1; // no go
c ~= [1,2,3]; // no go
// (compare to)
short[] s;
s ~= 1; // works
s ~= [1,2,3]; // works
}
(In reply to comment #5)
> (In reply to comment #4)
> > Commits pushed to master at https://github.com/D-Programming-Language/dmd
> >
> > https://github.com/D-Programming-Language/dmd/commit/8bc59cfe8e6896435f20ce1e9bdcc226942f59a8
> > fix Issue 5893 - Allow simple aliases for operator overloading
> >
> > https://github.com/D-Programming-Language/dmd/commit/2888ec45218e2e49048e9f96be2fa0481dc00e31
> > Merge pull request #989 from 9rnsr/fix5893
> >
> > Issue 5893 - Allow simple aliases for operator overloading
>
> The OP sample still fails.
The OP sample cannot compile, because ConcatAssignExp will try to instantiate opOpAssign!("~"). Correct sample code is:
class C
{
void concatAssign(C other) { }
void concatAssign(int other) { } // to demonstrate overloading
template opOpAssign(string s) if (s == "~") // FIXED
{ alias concatAssign opOpAssign; }
}
void main()
{
auto c = new C;
c.opOpAssign!"~"(c); // works
c.opOpAssign!"~"(1); // works
c ~= 1; // line 15
}
So, this bug is already fixed.
Comment #7 by andrej.mitrovich — 2013-02-05T17:33:07Z
(In reply to comment #6)
> template opOpAssign(string s) if (s == "~") // FIXED
This is actually worthy of an enhancement. If "~=" is found in opOpAssign the compiler should inform the user to use "~" instead. The same goes for +=, etc.
Comment #8 by schveiguy — 2013-02-06T08:55:06Z
(In reply to comment #6)
> (In reply to comment #5)
> > The OP sample still fails.
>
> The OP sample cannot compile, because ConcatAssignExp will try to instantiate
> opOpAssign!("~").
In my defense, I believe that originally it DID work the way I specified, whether it be by design or by accident ;)