On Wednesday, 19 January 2022 at 08:47:27 UTC, Enjoys Math wrote:
```
module expr;

import dots;
import operator;
import equation;
import var;
import var_expr;
import zz_const;

class Expr
{
public:
   void opBinary(string op)(string s) const
   {
      static if (op == "+")
      {
         Expr right = null;

         if (s == ".." || s == "..." || s == "....")
         {
            right = new Dots();
         }

         if (right !is null)
            return new Op("+", [this, right]);
      }
   }

   override string toString() const
   {
      assert(0);
   }

   Expr sub(Expr x, Expr y)
   {
      if (this == x)
         return y;
      return this;
   }

   Expr sub(Expr x, ref Var y)
   {
      return sub(x, new VarExpr(y));
   }

   Expr sub(ref Var x, Expr y)
   {
      return sub(new VarExpr(x), y);
   }

   Expr sub(int x, Expr y)
   {
      return sub(ZZ(x), y);
   }

   Expr sub(Expr x, int y)
   {
      return sub(x, ZZ(y));
   }

   Expr sub(ref Var x, ref Var y)
   {
      return sub(new VarExpr(x), new VarExpr(y));
   }

   Expr sub(ref Var x, int y)
   {
      return sub(new VarExpr(x), ZZ(y));
   }

   Expr sub(int x, ref Var y)
   {
      return sub(ZZ(x), new VarExpr(y));
   }

   override bool opEquals(Object o) {
      return this is o;
   }
}
```
See all the overloads I had to make to sub in order to bypass identity assignment for classes. I.e. Var can't be of type Expr. Anyway, this approach is not working because code calling `Expr.sub(int, Var)` is not seeing the definitions. It says no function matching those args, but clearly there are!

Try replacing methods sub with template:
```d
module expr;

import dots;
import operator;
import equation;
import var;
import var_expr;
import zz_const;

    class Expr
    {
    public:
       void opBinary(string op)(string s) const;

       override string toString() const;

       Expr sub(Expr x, Expr y)
       {
          if (this == x)
             return y;
          return this;
       }

        //template sub:
        Expr sub(T, U)(auto ref T x, auto ref U y){

            //transform parameter to Expr:
            static Expr expr(E)(auto ref E e){
                static if(is(E : Expr))
                    return e;
                        else static if(is(E : int))
                    return ZZ(e);
                        else static if(is(E : Var))
                    return new VarExpr(e);
                        else
                    static assert(0, "no impl " ~ E.stringof);
            }

            //call sub(Expr, Expr)
            this.sub(expr(x), expr(y));

        }

       override bool opEquals(Object o) ;
    }
    ```

Reply via email to