Jeff
Jeff

Reputation: 4423

Overloading operator<< c++; undefined reference to `std::basic_ostream

I am trying to overload operator<< in my code. If I comment out the lines where I try to use the << operator with my custom class, it compiles fine. The error almost looks like it doesn't like the c++ libraries (?).

All my research on this problem has stated that it is a linking problem. Most suggest using g++ instead of gcc. I am using g++ as my compiler, and I get this error still.

Code:

#include <iostream>
using namespace std;

//prototype the class and the functions
template<class T> class strange;
template<class T> ostream& operator<< (ostream& osObject, strange<T>& sObject);


//begin class
template <class T>
class strange
{
    public:
        // .... function prototypes go here.
            strange(T x,T y);
            friend ostream& operator<< <> (ostream& osObject, strange<T>& sObject);

    private:
    T a;
    T b;
};
// .... your function definitions go here
template <class T>
        strange<T>::strange(T first, T second){
        a = first;
        b = second;
}

template <class T>
ostream& operator<< (ostream& osObject, const strange<T>& sObject){
        osObject << sObject.a << ", " << sObject.b;
        return osObject;
}



int main()
{
    strange<int> x1(4,6) , x2(12,2) ;
    //strange<char> y1('m','n') , y2('m','n') ;
    cout << "x1 = " << x1 << endl;
    return 0;
}

Error:

test.cpp:(.text+0x7a): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, strange<int>&)'
collect2: ld returned 1 exit status

Any idea what is causing this?

Upvotes: 2

Views: 11404

Answers (1)

Bill Lynch
Bill Lynch

Reputation: 81936

I made two changes, one to the friend definition, and one to the prototype. This should compile:

#include <iostream>
using namespace std;

//prototype the class and the functions
template<class T> class strange;
template<class T> ostream& operator<< (ostream& osObject, const strange<T>& sObject);


//begin class
template <class T>
class strange
{
    public:
        // .... function prototypes go here.
            strange(T x,T y);
            friend ostream& operator<< <> (ostream& osObject, const strange<T>& sObject);

    private:
    T a;
    T b;
};
// .... your function definitions go here
template <class T>
        strange<T>::strange(T first, T second){
        a = first;
        b = second;
}

template <class T>
ostream& operator<< (ostream& osObject, const strange<T>& sObject){
        osObject << sObject.a << ", " << sObject.b;
        return osObject;
}



int main()
{
    strange<int> x1(4,6) , x2(12,2) ;
    //strange<char> y1('m','n') , y2('m','n') ;
    cout << "x1 = " << x1 << endl;
    return 0;
}

And this compiles in clang, g++ and at ideone

To explain the issue, the compiler is looking at link time for a definition for:

 std::ostream & operator<< <int>(std::ostream &, strange<int>&);

When you only have a definition for:

 std::ostream & operator<< <int>(std::ostream &, strange<int> const &);

This is because of the miscommunication between your prototypes (both the explicit one and the friend) and your definition.

Upvotes: 4

Related Questions