do you know, how to write signature of a function or method for operator<< for template class in C++? I want something like:
template <class A> class MyClass{
public:
friend ostream & operator<<(ostream & os, MyClass<A> mc);
}
ostream & operator<<(ostream & os, MyClass<A> mc){
// some code
return os;
}
But this just won't compile. Do anyone know, how to write it correctly?
All the below said, if you don't need an operator to be a friend, then don't make it a friend. For output operators in particular, in my opinion you should not make them friends. That is because if your class can be output to a stream, it should have equivalent get functions that provide the same data programmatically. And in that event, you can write a operator<< as a non-friend in terms of those get functions.
In case you have some good reason for making them friends, you can do a friend definition
template <class A> class MyClass {
public:
friend ostream & operator<<(ostream & os, MyClass<A> const& mc) {
// ...
}
};
That way you don't need the template<...> clause that gets you the type A. It's alreay known if you define the operator inside the template. Note that even though you defined it inside the template, it's not a member function. It's still a non-member, but has access to the names declared in the class (like the template parameter). For each instance of MyClass you create, a different non-template operator function is created out of that friend function that prints things.
If you want to define the template outside, you have to predeclare it to be able to declare a given specialization of it as a friend.
// predeclare it so you can make it a friend.
template <class A> class MyClass;
template <class A> ostream &operator<<(ostream &os, MyClass<A> const&);
template <class A> class MyClass{
public:
/* the "<A>" is needed - it says that a given instantiation of
that template is a friend, and not a non-template function. */
friend ostream & operator<< <A>(ostream & os, MyClass<A> const& mc);
};
template <class A>
ostream & operator<<(ostream & os, MyClass<A> const& mc){
// some code
return os;
}
That makes operator<< <Foo> a friend of MyClass<Foo>. If you were to omit the <A> or an also possible empty <>, the compiler would understand that as saying you made a non-template operator having concrete instead of templated parameters as friend.
The more easy but less "correct" solution is to make MyClass <Foo> have as friend all the operator << instantiations. So theoretically operator << <Bar> could access private members of MyClass <Foo>. It's not what is wanted, but it works too, gaining more access than needed. It gets rid of the need for forward declaring:
template <class A> class MyClass{
public:
/* make all instantiations friends. */
template<typename T>
friend ostream & operator<<(ostream & os, MyClass<T> const& mc);
};
template <class T>
ostream & operator<<(ostream & os, MyClass<T> const& mc){
// some code
return os;
}
Related
I have a problem to overload the << stream operator and I don't find the solution :
template<class T, unsigned int TN>
class NVector
{
inline friend std::ostream& operator<< (
std::ostream &lhs, const NVector<T, TN> &rhs);
};
template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};
It produces the following error message:
warning : friend declaration ‘std::ostream& operator<<(std::ostream&, const NVector&)’ declares a non-template function [-Wnon-template-friend]
error: ‘std::ostream& NVector::operator<<(std::ostream&, const NVector&)’ must take exactly one argument
How to solve that problem ?
Thank you very much.
There are two different issues in your code, the first is that the friend declaration (as the warning clearly says, maybe not so clear to understand) declares a single non-templated function as a friend. That is, when you instantiate the template NVector<int,5> it declares a non-templated function std::ostream& operator<<(std::ostream&,NVector<int,5>) as a friend. Note that this is different from declaring the template function that you provided as a friend.
I would recommend that you define the friend function inside the class definition. You can read more on this in this answer.
template <typename T, unsigned int TN>
class NVector {
friend std::ostream& operator<<( std::ostream& o, NVector const & v ) {
// code goes here
return o;
}
};
Alternatively you can opt for other options:
declare the operator<< template as a friend (will grant access to any and all instantiations of the template),
declare a particular instantiation of that template as a friend (more cumbersome to write) or
avoid friendship altogether providing a public print( std::ostream& ) member function and calling it from a non-friend templated operator<<. I would still opt to befriend the non-template function an provide the definition inside the templated class.
The second issue is that when you want to define an operator outside of the class of the left hand side argument, the operator is a free function (not bound to a class) and thus it should not be qualified:
template<class T, unsigned int TN>
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};
I am getting a compile error in my output stream operator and I cannot seem to find out how to fix it as I never received this error before:
linkedList.cpp:258: error: ‘std::ostream& linkedList<T>::operator<<(std::ostream&, linkedList<T>)’ must take exactly one argument
make: *** [linkedList.o] Error 1
Here is the definition of my operator<<
template <class T>
ostream& linkedList<T>::operator<<(ostream &output, linkedList<T> list)
{
node *curr;
curr=list.head;
while(curr!=NULL )
{
output << curr->data;
curr = curr->next;
}
return output;
}
Here it is in my header:
//ostream operator for printing the list
template <class T>
ostream &operator<<(ostream &output, linkedList<T> list);
Any help will be appreciated!
You defined it as a member function, you have to define it as a free standing (probably friend) function, either
outside your class
template <class U>
ostream& operator<<(ostream &output, linkedList<U> list){...}
in which case you also have to declare it inside the class as
template <class U> // note the different type name
friend ostream& operator<<(ostream &output, linkedList<U> list)
or
inside the class as
// no need for template, type is passed automatically the function is not templated anymore
friend ostream& operator<<(ostream &output, linkedList list){...}
The difference between these 2 declarations is a bit subtle, but for your purpose both work equally well. And probably you want to pass linkedList by const reference, linkedList<T>& list.
EDIT
A common mistake is to just declare the friend operator inside the class as
template<typename T>
class linkedlist
{
//....
friend ostream& operator<<(ostream& output, const linkList& list); // declaration only
}
then try to define it outside the class as
template<typename T>
ostream& operator<<(ostream& output, const linkList<T>& list){...}
Guess what? The code will compile, but won't link, as the declaration inside the class declares a non-template function, one for each type T you pass to linkList<T>. Then, when you declare e.g. linkList<int> lst, and try cout << lst, the compiler will see the declaration of the friend, which for it looks like
friend ostream& operator<<(ostream& output, const linkList<int>& list);
and will try searching for its definition. However there is no definition in the rest of the header, only the template operator, so the linker isn't able to find the implementation and will spit a linker error. Live example here.
It's all in the error message. This function that you declared:
template <class T>
ostream &operator<<(ostream &output, linkedList<T> list);
is a member function of linkedList<T> that takes two arguments. All the binary operators (+, *, <<, ... all except for the call operator ()), when defined as member functions, must take exactly one argument, hence the error. What you had intended to do was to declare a non-member function, external to the class:
template <typename T>
class linkedList { .. };
template <typename T>
ostream &operator<<(ostream &output, linkedList<T> list) {
// implementation
}
You could also define it as a non-member friend inside the class definition:
template <class T>
class linkedList {
...
friend ostream &operator<<(ostream &output, linkedList list){
...
}
...
};
I have a problem to overload the << stream operator and I don't find the solution :
template<class T, unsigned int TN>
class NVector
{
inline friend std::ostream& operator<< (
std::ostream &lhs, const NVector<T, TN> &rhs);
};
template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};
It produces the following error message:
warning : friend declaration ‘std::ostream& operator<<(std::ostream&, const NVector&)’ declares a non-template function [-Wnon-template-friend]
error: ‘std::ostream& NVector::operator<<(std::ostream&, const NVector&)’ must take exactly one argument
How to solve that problem ?
Thank you very much.
There are two different issues in your code, the first is that the friend declaration (as the warning clearly says, maybe not so clear to understand) declares a single non-templated function as a friend. That is, when you instantiate the template NVector<int,5> it declares a non-templated function std::ostream& operator<<(std::ostream&,NVector<int,5>) as a friend. Note that this is different from declaring the template function that you provided as a friend.
I would recommend that you define the friend function inside the class definition. You can read more on this in this answer.
template <typename T, unsigned int TN>
class NVector {
friend std::ostream& operator<<( std::ostream& o, NVector const & v ) {
// code goes here
return o;
}
};
Alternatively you can opt for other options:
declare the operator<< template as a friend (will grant access to any and all instantiations of the template),
declare a particular instantiation of that template as a friend (more cumbersome to write) or
avoid friendship altogether providing a public print( std::ostream& ) member function and calling it from a non-friend templated operator<<. I would still opt to befriend the non-template function an provide the definition inside the templated class.
The second issue is that when you want to define an operator outside of the class of the left hand side argument, the operator is a free function (not bound to a class) and thus it should not be qualified:
template<class T, unsigned int TN>
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};
The following code works, but i would like to move ostream& operator<< outside of the class declearation as i have with hash::operator[].
#include<iostream>
#include<map>
using namespace std;
template <class T>
class hash {
private:
map<string, T> _map;
public:
T& operator[] (string x);
friend ostream& operator<<(ostream& out, const hash<T> &rhs) { return out << "test"; }
};
template <class T>
T & hash<T>::operator[](string x) {
return _map[x];
}
int main () {
hash<int> myobject;
myobject["a"] = 1;
cout << myobject["a"] << endl;
cout << myobject << endl;
return 0;
}
I have tried:
template <class T>
ostream& operator<<(...) {
return out << "test";
}
and
ostream& operator<<(...) {
return out << "test";
}
as well as a few other combinations to no avail.
Since it does not seem that this question is getting closed as exact duplicate, I will explain what your program does.
template <typename T>
class test {
int private_field;
friend std::ostream& operator<<( std::ostream&, test<T> const & );
};
// ???
int main() {
std::cout << test<int>() << std::endl;
}
Templates are instantiated on demand (unless you explicitly instantiate them), that means that in this particular program test is instantiated only as test<int>. When the compiler instantiates the template (because it was requested in main) it will process the template definition. At this point the behavior is similar to rewriting the code with the substituted type at the point of definition (in this case right before main):
class test<int> {
friend std::ostream& operator<<( std::ostream&, test<int> const & );
};
Now, if you look at the instantiated template, you can note that the friend declaration is befriending a non templated function. So in this particular program you can fill in the ??? with that particular function:
std::ostream& operator<<( std::ostream& o, test<int> const & t ) {
return o << t.private_field;
}
The problem here is that this is not easily extensible. The code of that operator<< is the same for test<int> than it is for test<double>, so there should be no need to rewrite the same function for all instantiating types!
At this point there are two options, the first one is, as you have already identified, providing the definition of the function inside the class. The compiler will then process and define the function whenever the type is being instantiated. This solution creates non-templated functions on demand for each template instantiation (which is the option I would do, even with the quirks and strangeness of lookup here).
Now, if you really want to avoid providing the definition inside the templates class, and you still want to provide a single implementation, then you have to resort to providing a templates operator<<. At this point you have two different options, you can declare all instantiations of the template (which I don't quite like, as it opens to too many others), or you can befriend a single specialization of the template function (cleaner regarding access, more cumbersome to write).
The first case is:
template <typename T>
class test {
template <typename U>
friend std::ostream& operator<<( std::ostream&, test<U> const & );
};
template <typename T>
std::ostream& operator<<( std::ostream&, test<T> const & ) { ... }
The second case requires a couple of forward declarations:
template <typename T> test;
template <typename T> std::ostream& operator<<( std::ostream&, test<T> const & );
template <typename T>
class test {
friend std::ostream& operator<< <T>( std::ostream&, const test<T>& );
};
template <typename T>
std::ostream& operator<<( std::ostream&, test<T> const & ) { ... }
There is of course another option: do not declare friends at all. Provide a print(std::ostream&) public function in your class that has the implementation, and provide a non-templated operator<< that just calls print on the second argument.
You have to be careful when you use friend and template
#include<iostream>
#include<map>
template <class T>
class MyHash{
public:
// ... use your T template here
template <class U>
friend ostream& operator<<(ostream& out, const MyHash<U> &rhs);
};
// ...
template <class U>
ostream& operator<<(ostream& out, const MyHash<U> &rhs){ return out << "test"; }
you need to use a different template U because operator<< is a friend method (external), if we use T instead of U, we will have : ambiguous definition in template .
Change hash by MyHash to avoid ambiguities.
Edit :
The error that you get here is :
error C2676: '<' binaire : 'std::string' ne définit pas cet opérateur
ou une conversion vers un type acceptable pour l'opérateur prédéfini
because you forgot to include <string> in "hash.h". That header defines the < operator.
And also try moving the definition of operator[] and operator<< directly into "hash.h"
Both the declaration and definition of templates must be included. This is because in some compilers template functions cannot be compiled and linked independently, since they are generated on request for the specific types they are instantiated with.
Change the #include "hash.cpp" to #include "hash.h"
How can I make the insertion (<<) and/or extraction (>>) operator overloaded in a template class WITHOUT making it inline. I would like to have the << or >> operator as a friend class.
I know how to make it inline
example of inline in a matrix class
friend ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
...
// create the ostr
return ostr;
}
but I'd like to have the code outside of the templateclass definition.
g++ told me to add <> after the function name so I did but when I tried to instansiate a matrix of type SOMETYPE it gave me an error that it didn't know how to extract or insert for that type.
If you really want to define the operator externally and befriend only the operator instantiation that coincides in type with this template instantiation, the correct syntax is:
template <typename T> class test; // forward declare template class
template <typename T> // forward declare the templated operator
std::ostream& operator<<( std::ostream&, test<T> const & );
template <typename T>
class test { // define the template
friend std::ostream& operator<< <T>( std::ostream&, test<T> const & ); // befriend
};
template <typename T> // define the operator
std::ostream& operator<<( std::ostream& o, test<T> const & ) {
return o;
}
In most cases it is not worth the hassle to pull the definition out of the class, considering that you still need to provide it in a header and the extra work required.
Also note that there are slight differences for the compiler regarding lookup. In the case where the function is inlined inside the class definition, the compiler will not find that function unless one of the arguments is actually of the type of the template, so it effectively reduces the visibility and the amount of work that the compiler has to do (if the templated operator<< is defined outside of the class, the compiler will find it as a candidate for overload resolution in all places where it finds a << b, only to discard it in all cases where the second argument is not a test<T> (and it will show the templated operator as a candidate in all error messages where it cannot match operator<<, which is a long enough list already).
Try something like:
template <typename T> class Matrix;
template <typename T> std::ostream& operator<<(std::ostream& ostr, const Matrix<T>& m);
template <Typename T>
class Matrix
{
public:
friend ostream& operator<< <T> (ostream& ostr, const Matrix<K>& inputMatrix);
};
// This must be in the same translation unit as the class definition!
template<typename T>
ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
// ...
return ostr;
}
Translation unit reference
re-re-edited to addressed the comments made by aschepler and dribeas.
Place the code in the header, outside the class definition. Or, place it in a .tcc file and include it at the bottom of the header.