2

I' ve been trying to make a small library for working with big integers, just as practice, but I get this error for no apparent reason:

Use of overloaded operator '+' is ambiguous (with operand types 'BigNum::BigInt' and 'int')

This is the class definition:

namespace BigNum {

    class BigInt {
    public:
        BigInt();
        BigInt(int64_t n);
        BigInt(std::string s);

        friend std::istream& operator>> (std::istream& in, BigInt& n);
        friend std::ostream& operator<< (std::ostream& out, BigInt n);

        friend bool operator< (const BigInt& a, const BigInt& b);
        friend bool operator> (const BigInt& a, const BigInt& b);
        friend bool operator== (const BigInt& a, const BigInt& b);
        friend bool operator!= (const BigInt& a, const BigInt& b);
        friend bool operator<= (const BigInt& a, const BigInt& b);
        friend bool operator>= (const BigInt& a, const BigInt& b);

        operator bool();
        explicit operator int();
        friend void swap (BigInt& a, BigInt& b);

        friend BigInt operator+ (BigInt a, BigInt b);

    private:
        std::vector<int> digits; 
        std::size_t number_of_digits;
    };
}

And these are the methods used:

BigNum::BigInt::BigInt(int64_t n) {

    if (n == 0) {
        BigInt();
        return;
    }

    // The number is stored in reverse
    for (; n; n /= 10)
        digits.emplace_back(n % 10);

    number_of_digits = digits.size();
}

std::ostream& BigNum::operator<< (std::ostream& out, BigNum::BigInt n) {

    for (auto it = n.digits.rbegin(); it != n.digits.rend(); ++it)
        out << *it;

    return out;
}

void BigNum::swap (BigNum::BigInt& a, BigNum::BigInt& b) {

    BigNum::BigInt temp(a);
    a = b;
    b = temp;
}

BigNum::BigInt BigNum::operator+ (BigNum::BigInt a, BigNum::BigInt b) {

    if (a < b)
        BigNum::swap(a, b);

    BigNum::BigInt result(a);

    int transport = 0;
    for (std::size_t i = 0; i < b.number_of_digits; ++i) {

        result.digits[i] += b.digits[i] + transport;
        transport         = result.digits[i] / 10;
        result.digits[i] %= 10;
    }

    if (transport)
        result.digits.emplace_back(transport);

    ++result.number_of_digits;

    return result;
}

If I write something like:

BigNum::BigInt a = 2;
BigNum::BigInt b = a + 1;

I get that error. I've made the int typecast explicit, but it didn't help out. I don't want to also make the constructor explicit, as that will mean that I'll no longer be able to assign an int to a BigInt (like I did in the previous example). How can I fix this?

Semetg
  • 129
  • 2
  • 8
  • have a look on this : https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading – Steve Ruben Apr 10 '18 at 16:59
  • 2
    `friend BigInt operator+ (BigInt a, BigInt b);` is friend function, not a member. `BigNum::BigInt BigNum::operator+ (BigNum::BigInt a, BigNum::BigInt b)` is defined as a member of `BigNum`. `BigNum::operator+` should be `operator+`. – user4581301 Apr 10 '18 at 17:02
  • `int64_t` is not the same type as `int`, but you can have a narrowing conversion to `int` or an integer promotion to `int64_t`. They are distinct types and you have a converting constructor from `int64_t` to `BigNum::BigInt` in your system. However, you also have a conversion operator to int as well. So, when converting the integers to `BigInt`s, it doesn't know which conversion to use. Hence it is ambiguous. – callyalater Apr 10 '18 at 17:04
  • @user4581301 if I change it that way, I no longer have access to any of the private members – Semetg Apr 10 '18 at 17:06
  • 1
    Yes you do. That's what the `friend` declaration gives you. – Silvio Mayolo Apr 10 '18 at 17:07

1 Answers1

8

It's not enough to have one explicit conversion operator, you need to make sure that every conversion to a built-in type is explicit. In particular, you should try

explicit operator bool();

to prevent a + 1 from matching the conversion-then-promotion sequence (int)(bool)a and calling operator+(int, int).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720