I have a base Class akin to the code below. I'm attempting to overload << to use with cout. However, g++ is saying:
base.h:24: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, Base<T>*)’ declares a non-template function
base.h:24: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
I've tried adding <> after << in the class declaration / prototype. However, then I get it does not match any template declaration
. I've been attempting to have the operator definition fully templated (which I want), but I've only been able to get it to work with the following code, with the operator manually instantiated.
base.h
template <typename T>
class Base {
public:
friend ostream& operator << (ostream &out, Base<T> *e);
};
base.cpp
ostream& operator<< (ostream &out, Base<int> *e) {
out << e->data;
return out;
}
I want to just have this or similar in the header, base.h:
template <typename T>
class Base {
public:
friend ostream& operator << (ostream &out, Base<T> *e);
};
template <typename T>
ostream& operator<< (ostream &out, Base<T> *e) {
out << e->data;
return out;
}
I've read elsewhere online that putting <> between << and () in the prototype should fix this, but it doesn't. Can I get this into a single function template?
It sounds like you want to change:
friend ostream& operator << (ostream& out, const Base<T>& e);
To:
template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);
Gcc is rightly warning you. Despite it's appearances (it takes Base argument), it is not a function template.
Your class definition has a non-template declaration of the friend function (without the template), but the friend function definition later on is a function template (i.e. starts with template..).
Also your operator<< takes a Base *. This is not correct. It should be Base const & to retain it's built-in semantics
Probably you are looking at something as below:
template <typename T>
class Base {
public:
friend ostream& operator << (ostream &out, Base<T> const &e){
return out;
};
};
int main(){
Base<int> b;
cout << b;
}
If you want fully templated, then this is probably what you want. But I am not sure how much useful this is over the previous one. Since the lookup involves ADL, you will never be able to resolve to any condition where T is not equal to U (as long as the call is from a context not related to this class e.g. from 'main' function)
template <typename T>
class Base {
public:
template<class U> friend ostream& operator << (ostream &out, Base<U> const &e){
return out;
};
};
int main(){
Base<int> b;
cout << b;
}
Probably what you are looking for is:
template <typename T>
class Base;
template <typename T>
ostream& operator<< (ostream &, const Base<T>&);
template <typename T>
class Base
{
public:
template<>
friend ostream& operator << <T>(ostream &, const Base<T> &);
};
template <typename T>
ostream& operator<< ( ostream &out, const Base<T>& e )
{
return out << e->data;
}
This friends only a single instantiation of the template, the one where the operator's template parameter matches the class's template parameter.
UPDATE: Unfortunately, it's illegal. Both MSVC and Comeau reject it. Which raises the question of why the original error message suggested pretty much EXACTLY this approach.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With