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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…