On 05/21/2013 05:31 PM, Steven Schveighoffer wrote:
On Mon, 20 May 2013 11:15:32 -0400, John Colvin
<[email protected]> 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.)