Thread overview
Function prototype overloading does not work ?
Jan 19, 2022
Enjoys Math
Jan 19, 2022
Hipreme
Jan 19, 2022
vit
January 19, 2022
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!

January 19, 2022

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!

Firstly, in my opinion, you should be using auto ref which will do the same thing as generating by reference and by value declarations. Or you could even use in as the compiler will optimize the call for passing it by reference.

Now, you could have some self contained example for we being able to test it

January 19, 2022

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:

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) ;
    }
    ```
January 19, 2022

On 1/19/22 3:47 AM, 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!

sub(int, ref Var) exists, but not sub(int, Var). Is your Var an lvalue?

Without more code context, this is hard to diagnose. Can you post the offending call?

-Steve