digitalmars.D - covariance, operator overloads, and interfaces
- Steven Schveighoffer (32/32) May 11 2010 The situation with interfaces and operators is getting worse and worse a...
- Steven Schveighoffer (33/35) May 11 2010 Here's an idea.
- Michel Fortin (15/28) May 11 2010 Can't you repeat the opBinary template in the ArrayList class with a
- Andrei Alexandrescu (5/33) May 11 2010 He already mentioned "repeating the template in all derived classes".
The situation with interfaces and operators is getting worse and worse as I try to implement it. Here is another issue I have found. Previously in dcollections, I support the ~ operator on Lists. The relevant interface looked something like this: interface List { List opCat(List rhs); } So something like an array list would use covariance to make the syntax sugar more pleasant: class ArrayList : List { ArrayList opCat(List rhs); } Now, you can do things like this: ArrayList al, al2; al = al ~ al2; Fine and dandy. However, with the new operator overloading scheme, I must define the operator as follows: interface List { List concat(List rhs); List opBinary(string op)(List rhs) if (op == "~") { return concat(rhs); } } But now I lose covariance, the above usage no longer compiles. I don't know how to solve this without dropping interfaces, or repeating the template in all derived classes. -Steve
May 11 2010
On Tue, 11 May 2010 09:33:38 -0400, Steven Schveighoffer <schveiguy yahoo.com> wrote:I don't know how to solve this without dropping interfaces, or repeating the template in all derived classes.Here's an idea. What if when using an auto return on a template, it becomes automatically covariant for derived classes? For example: interface List { List append(List l); auto opOpAssign(string op : "~=")(List rhs) { return append(l); } } class ArrayList : List { ArrayList append(List l); } ArrayList al = new ArrayList; ArrayList al2 = new ArrayList; auto x = (al ~= al2); when compiling the above line, the compiler should recognize that the template returns auto. It does the calculation of what type to return based on the context. In the context of ArrayList, append returns ArrayList, so opOpAssign should return ArrayList. Problems may arise if the compiler can easily determine the result when dealing with straight interfaces, but cannot easily determine when dealing with derived classes. I think in those cases, the compiler should just output an error, and the user will be forced to concretely specify the return type, or fix their method to be more covariant-friendly. How does this sound? I'd also like to see this for final interface functions as well. -Steve
May 11 2010
On 2010-05-11 09:33:38 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:interface List { List concat(List rhs); List opBinary(string op)(List rhs) if (op == "~") { return concat(rhs); } } But now I lose covariance, the above usage no longer compiles. I don't know how to solve this without dropping interfaces, or repeating the template in all derived classes.Can't you repeat the opBinary template in the ArrayList class with a covariant return? class ArrayList : List { ArrayList concat(List rhs); ArrayList opBinary(string op)(List rhs) if (op == "~") { return concat(rhs); } } Not very elegant, but I think it'll work. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
May 11 2010
Michel Fortin wrote:On 2010-05-11 09:33:38 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:He already mentioned "repeating the template in all derived classes". This is another place in which we need typeof(class) to yield the class being currently compiled. Andreiinterface List { List concat(List rhs); List opBinary(string op)(List rhs) if (op == "~") { return concat(rhs); } } But now I lose covariance, the above usage no longer compiles. I don't know how to solve this without dropping interfaces, or repeating the template in all derived classes.Can't you repeat the opBinary template in the ArrayList class with a covariant return? class ArrayList : List { ArrayList concat(List rhs); ArrayList opBinary(string op)(List rhs) if (op == "~") { return concat(rhs); } } Not very elegant, but I think it'll work.
May 11 2010