The community reviewed whether to reopen this question 9 months ago and left it closed:
开发者_JAVA百科Original close reason(s) were not resolved
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.
changing
friend ostream& operator << (ostream& out, const Base<T>& e);
to
friend ostream& operator << <T>(ostream& out, const Base<T>& e);
should work as well--I just solved an identical problem in this way.
changing
friend ostream& operator << (ostream &out, Base<T> *e)`
To
template<T> friend ostream& operator << (ostream &out, Base *e)
change
ostream& operator<< (ostream &out, Base<int> *e) {
out << e->data;
return out;
}
to
ostream& operator<< (ostream &out, T *e) {
out << e->data;
return out;
}
精彩评论