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