Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
291 views
in Technique[技术] by (71.8m points)

c++ - error when trying to overload << operator and using friend function

I am trying to overload << operator and using friend function. Below code chunk works just fine.

template <class T>
class Mystack{
    friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
    {
        d.print(s);
        return s;
    } 
};

Since it is friend function I would obviously want to define it outside the class without using scope resolution operator. But when I try that I get error.

template <class T>
class Mystack{
    friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d); 
};
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
    d.print(s);
    return s;
}

Below is the code snippet for main

Mystack<int> intstack;
std::cout << intstack;

ERROR : Unresolved extrernal symbol.

P.S: Its not the complete running code. Just a sample. Kindly bear.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);

declares and befriends a non-template operator<< function. So Mystack<int> would have as its friend a non-template function std::ostream& operator<<(std::ostream& s, Mystack<int> const& d);, etc.

template<class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
    d.print(s);
    return s;
}

defines an operator<< function template.

The two are not the same. When you write std::cout << intstack;, the overload resolution rules resolve it to the non-template operator<< function you declared, but it isn't defined, so you get a linker error.

There's no way to define a non-template function for every instantiation of a class template outside the class template. You can, however, befriend a specialization of your operator<< function template:

// forward declarations
template <class T>
class Mystack;
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);

template <class T>
class Mystack
{
    friend std::ostream& operator<< <T>(std::ostream& s, Mystack<T> const& d); 
//                                  ^^^
};

or befriend every specialization of the function template, which is worse from an encapsulation point of view (since, e.g., operator<< <int> would be a friend of Mystack<float>):

template <class T>
class Mystack
{
public:
    template <class U>
    friend std::ostream& operator<<(std::ostream& s, Mystack<U> const& d);
};

or just define the friend function inside the class.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...