0
#include <iostream>
using namespace std;

class StringNum {
public:
    string s;
    StringNum() {s = "";}
public:
    StringNum(int n) {
        for (int i=1; i<=n; i++) s += "x";

    }

    operator int () {
        return s.length();
    }

    StringNum operator - (StringNum v) {
        int len = s.length() - v.s.length();
        StringNum res;
        for (int i=1;i<=len;i++) res.s += "x";
        return res;
    }

    /* // long solution. But this will allow the program to run.
    template <class T>
    StringNum operator - (T value) {
        return (*this) - StringNum(value);
    }
    */
};

int main()
{
    StringNum x(4);
    cout << 3 - x; // this compiles
    cout << x - 3; // error: ambiguous overload for operator - 
                   // change the program so that the 2nd line output 2
    return 0;
}

So I have a class that can be upcast from int/downcast to int (this is the simplified version, in the actual version StringNum is HighPrecisionFloat, and int is int/float/double/.. . etc).

When I compile the program, the error message

In function 'int main()':|
error: ambiguous overload for 'operator-' (operand types are 'StringNum' and 'int')|
note: candidate: operator-(int, int) <built-in>|
note: candidate: StringNum StringNum::operator-(StringNum)|

This happens because there are 2 ways to understand x - 3 :

a) int(x) - 3
b) x - StringNum(3)

One way to do this is to use template for each operator (+, -, *, /, dot product, etc...) But that is not very convenient because I have to write templates for each operator.

Is there a better solution to this problem? I wish to call x - StringNum(3). Thank you.

Huy Le
  • 1,439
  • 4
  • 19
  • 4
    Unrelated to your problem, but please take some time to read [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – Some programmer dude Feb 14 '20 at 12:11
  • @Someprogrammerdude I only do that in single-file programs :D so that shouldn't be a problem. #include , using namespace std; are only used in competitions, not work – Huy Le Feb 14 '20 at 12:14
  • 4
    Until I (and others) try and compile your program with another compiler. 10 secs saved for you, hours wasted for people trying to help you. – Richard Critten Feb 14 '20 at 12:34
  • I have edited my post. Thank you. – Huy Le Feb 14 '20 at 12:43

1 Answers1

1

You can make your constructor and conversion to int explicit.

The compiler won't make implicit conversion between those types anymore, but you can still use them like so.

auto stringNum = StringNum{3}; //int to StringNum
int y = static_cast<int>(stringNum);
Kaldrr
  • 2,780
  • 8
  • 11
  • 1
    But that removes the ability to do: int res = x - 2 (calculation without explicit conversion). – Huy Le Feb 14 '20 at 12:43
  • @HuyĐứcLê you should mention what you want to be able to do in the question. `x-2` would still work using the built-in `-`. – rustyx Feb 14 '20 at 12:45
  • @HuyĐứcLê Adding `explicit` here mostly depends what you really want to achieve, but generally adding it to single parameter constructors is good practice, as it disables surprising conversions that might happen. – Kaldrr Feb 14 '20 at 12:48
  • It worked. The answer is to make the constructor explicit. Thank you for your help. – Huy Le Feb 14 '20 at 12:55