Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ compiler giving << type errors for expressions, but works in Visual Studio

Ok, I think this might just be a version issue but I'm new to this. I have a main file that uses my overridden << operator for a BigInt class I've implemented:

BigInt a = 3;
cout << a << endl;
cout << (a+a) << endl;

In Visual Studio, the compiler understands everything just fine and it runs great. But moving over to Ubuntu 14.04, makeing with my Makefile (which uses plain g++ commands) gives me a bazillion type errors that are caused by the third line (and any other line that uses cout with an expression). If I remove the third line, it compiles great. The first error is:

main.cpp:23:8: error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'BigInt')
    cout << (a+a);
         ^

This is confusing because my << operator function takes reference args:

// in BigInt.h, in class' public section:

BigInt operator+(BigInt const& other) const;
friend std::ostream & operator<<(std::ostream& os, BigInt& num);


// in BigInt.cpp:

BigInt BigInt::operator+(BigInt const& other) const {
    // call appropriate helper based on signs
    if (this->neg == other.neg) {
        return sum(other);
    }
    else {
        return difference(other);
    }
}

ostream & operator<<(ostream& os, BigInt& num) {
    if (num.dataLength == -1) {
        os << "**UNDEFINED**";
    }
    else {
        if (num.neg) os << "-";
        if (num.dataLength == 0) {
            os << "INFINITY";
        }
        else {
            // print each digit
            for (int i = num.dataLength - 1; i >= 0; i--) {
                os << (short)num.data[i];
            }
        }
    }
    return os;
}

So why does the first cout work but not the second? Is there a way to run g++ such that it can work?

like image 714
vestlen Avatar asked Nov 28 '22 01:11

vestlen


1 Answers

ostream & operator<<(ostream& os, BigInt& num)

should take a BigInt const& num. MSVC is non-compliant with regards to this. g++ does not have this extension.

Make sure you change both the declaration in the header and the definition in the BigInt.c file. (Also, it is normal to use .c for files containing C code, and .cpp for files containing C++ code.)

The reason is that (a+a) creates a temporary BigInt, which can't be bound to a non-const reference. The first cout works because a is a local variable, not a temporary, so can be passed as a normal (non-const) reference.

Aside from the issue with temporaries, it is good practice to apply const-correctness: make things const unless you actually need to change them. This can help prevent mistakes. Note that std::ostream& os cannot be const, you really do change it by writing to it.

like image 124
BoBTFish Avatar answered Dec 05 '22 03:12

BoBTFish