www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Function prototype overloading does not work ?

reply Enjoys Math <enjoysmath gmail.com> writes:
```
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!
Jan 19 2022
next sibling parent Hipreme <msnmancini hotmail.com> writes:
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
Jan 19 2022
prev sibling next sibling parent vit <vit vit.vit> writes:
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) ; } ```
Jan 19 2022
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
Jan 19 2022