friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
declares a non template version friend
, so you would have to implement
std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
for every T
you use:
std::ostream& operator<<(std::ostream& os, const Derived<int>& dt) {
return os << dt.data_;
}
And so on.
A way to do it without duplicate code is with definition inside the class:
template <typename T>
class Derived : public IBase
{
public:
explicit Derived(T data);
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt)
{
return os << dt.data_;
}
private:
T data_;
};
Demo
An other alternative is to make the function template.
// Forward declarations
template <typename T> class Derived;
template <typename T> std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
And then in Derived
, you have 2 choices:
Declare each the template method friend:
template <typename T2>
friend std::ostream& operator<<(std::ostream& os, const Derived<T2>& dt);
So std::ostream& operator<<(std::ostream& os, const Derived<int>& dt)
has access to private members of Derived<int>
, but also to the ones of Derived<char>
Demo
Declare only the template which matches the argument:
friend std::ostream& operator<< <>(std::ostream& os, const Derived& dt);
and so std::ostream& operator<<(std::ostream& os, const Derived<int>& dt)
doesn't have access to private members of Derived<char>
.
Demo