opDispatch and operator overloads
Timon Gehr
timon.gehr at gmx.ch
Tue May 21 12:36:31 PDT 2013
On 05/21/2013 05:31 PM, Steven Schveighoffer wrote:
> On Mon, 20 May 2013 11:15:32 -0400, John Colvin
> <john.loughran.colvin at gmail.com> wrote:
>
>> struct S {
>> auto opDispatch(string s)(A i){}
>> }
>>
>> struct A {}
>>
>> void main() {
>> S s;
>> A a;
>> s + a; //Error: incompatible types for ((s) + (a)): 'S' and 'A'
>> }
>>
>> It would be really nice if opDispatch could catch missing operator
>> overloads.
>
> Not sure this can work. opDispatch takes a string identifying the
> function name, but opBinary is a template that ALSO needs a string.
>
> I suppose the string parameter to opDispatch could be the explicit
> instantiation:
>
> s.opDispatch!"opBinary!\"+\""(a)
>
It is parsed in a different way as is assumed here, the AST after
opDispatch rewrite looks like this:
(s.opDispatch!"opBinary")!"+"(a);
(which is a parse error with DMD due to a parser bug. It assumes this is
a C-style cast and bails out. The internal AST representation allows
this just fine though.)
> but that would seem extremely difficult to handle, you'd kind of need a
> parser to deal with it.
>
This handles your case using opDispatch:
import std.stdio,std.conv,std.algorithm,std.array;
string commaSep(T...)(T args){
string r="";
foreach(a;args) r~=a.to!string~",";
return r[0..$-!!$];
}
struct S{
template opDispatch(string name){
template opDispatch(T...){
auto opDispatch(S...)(S args){
writeln(this,".",name,"!"~T.stringof~"(",commaSep(args),")");
}
}
}
}
void main(){
S s;
s.opBinary!"+"(2); // ok
// s.foo(); // error. should IMO be fixed.
s.foo!()(); // ok
s.bar!([1,2,3],int)("123"); // ok
}
> what is the problem with just defining opBinary to catch missing
> operator overloads?
>
It is more boilerplate.
https://github.com/D-Programming-Language/phobos/blob/bcf7dd9bd268956754bf1a034728bef29619e858/std/typecons.d#L2654
>> Also, would it be a good idea to have free functions of all the
>> operators (opOpAssign etc...) for builtin types somewhere? It's
>> occasionally useful in generic wrappers.
>
> The name of operator overloads are the actual operators. The
> opOpAssign, etc, are hooks. Use the actual operators in generic code.
> A use case to discuss may be more helpful.
>
Eg. use a single opDispatch to forward missing operations to a built-in
member. The opDispatch/operator overloading limitation is not the only
thing that currently prevents this from working nicely though.
(eg. opDispatch does not naturally support variable-length instantiation
chains.)
More information about the Digitalmars-d
mailing list