using a template class as an argument - c++

Is there any way of creating a function that accepts any version of a given
template class?
e.g. this works:
ostream& operator << (ostream &out,const Vector<int>& vec);
but this doesn't:
ostream& operator << (ostream &out,const Vector& vec);
Is it possible to get the second line to work somehow for any version of vector?
e.g. vector<int> and vector<double> without having to write 2 separate functions?
Added to question:
I've made op<< a template function like you've suggested. In order to make it a friend function of the vector class I tried adding the following to the Vector class definition, but it didn't work:
friend ostream& operator << (ostream &out, const Vector<T>& vec);
any ideas what can be done to fix it?

Sure, make it a template function:
template <typename T>
ostream& operator << (ostream &out,const Vector<T>& vec);

template <class T>
ostream& operator << (ostream &out,const Vector<T>& vec);

As already pointed out something like this should work:
template <typename T>
ostream& operator << (ostream &out,const Vector<T>& vec) {
// body here
}
As for the friend requirement, that is most easily handled like this:
template <typename T>
ostream& operator << (ostream &out,const Vector<T>& vec) {
vec.print_on( out );
return out;
}
However, normally I would think of any output operator like this that requires access to the internals of the class to be showing you a mistake in your Vector class. It really only ought to need to use the public interface to do the display.
The other thing is that you might also want to template the output stream itself so that you can preserve its type:
template <typename O, typename C, typename T>
std::basic_ostream<O, C>& operator << (std::basic_ostream<O, C> &out,const Vector<T>& vec) {
vec.print_on( out );
return out;
}
The Vector's print_on can still use ostream.

Related

Overloading operator << in a template class

I'm sorry if this question has been answered allready but I have a read a lot of questions considering overloading this operator in a template class but I haven't found a particular case like mine.
This is my code:
#include <iostream>
using std::cout;
using std::endl;
using std::ostream;
template <typename T>
class Class
{
T x;
public:
friend ostream& operator << (const Class<T>&, ostream& out);
};
template <typename T>
ostream& operator << (const Class<T>&, ostream& out)
{
return (out << out.x << endl);
}
int main()
{
Class<short> object;
cout << object << endl;
}
And I get this error on last line:
Error 1 error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Class' (or there is no acceptable conversion) g:\ucenje\objektno orijentirano programiranje\template3\template3\main.cpp 25 1 template3
1.std::ostream should be the 1st parameter of operator<<, so
template <typename T>
ostream& operator << (const Class<T>&, ostream& out)
should be
template <typename T>
ostream& operator << (ostream& out, const Class<T>& c)
2.You defined operator<< as a template function, but friend ostream& operator << (const Class<T>&, ostream& out); points to a non-template function, you should change it to
friend ostream& operator<< <T>(ostream& out, const Class<T>& c);
And add some forward declarations before the declaration of the class:
template <typename T>
class Class;
template <typename T>
ostream& operator << (ostream& out, const Class<T>& c);
LIVE1
Or you can define operator<< as non-template function inside the definition of class.
template <typename T>
class Class
{
T x;
public:
friend ostream& operator<< (ostream& out, const Class<T>& c)
{
out << c.x << endl;
return out;
}
};
LIVE2
The arguments to the operator<< functions have been switched, it should be e.g
friend ostream& operator << (ostream& out, const Class<T>&1);
The left-hand side of all binary operators is always the first argument, and the right-hand side is the second argument.

How to use std::cout with my (templated) class?

I would like to overload the << operator, to print out a class instance to the console like this:
std::cout << instance << std::endl;
I've found a solution here: https://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx
But I cannot use it, because my class is templated:
template<typename T>
myClass {
//code...
};
Edit:
I get an error, if I try to define it inside the class body: it must take only one argument
Sure you can use the example, just adapt it for your template.
Instead of
ostream& operator<<(ostream& os, const Date& dt)
you would need
template<class T>
ostream& operator<<(ostream& os, const myClass<T>& dt)
You can try this (adapt it to your code):
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// write obj to stream
return os;
}

error when trying to overload << operator and using friend function

I am trying to overload << operator and using friend function.
Below code chunk works just fine.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
};
Since it is friend function I would obviously want to define it outside the class without using scope resolution operator. But when I try that I get error.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
};
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
Below is the code snippet for main
Mystack<int> intstack;
std::cout << intstack;
ERROR : Unresolved extrernal symbol.
P.S: Its not the complete running code. Just a sample. Kindly bear.
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.

Using overloaded output operator for templated class: Undefined symbols for architecture x86_64 [duplicate]

I am trying to overload << operator and using friend function.
Below code chunk works just fine.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
};
Since it is friend function I would obviously want to define it outside the class without using scope resolution operator. But when I try that I get error.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
};
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
Below is the code snippet for main
Mystack<int> intstack;
std::cout << intstack;
ERROR : Unresolved extrernal symbol.
P.S: Its not the complete running code. Just a sample. Kindly bear.
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.

Implementation of friend overload << operator with templates

I can't figure out the correct syntax for templated friend overloaded operators. Using the code (I'm only showing the relevant stuff) from the class header (please don't tell me to change anything from this section):
#include <iostream>
using namespace std;
template <typename T>
class List;
template <typename T>
class Queue;
template <typename T>
class Stack;
template <typename T>
class Node{
private:
friend class List<T>;
friend class Stack<T>;
friend class Queue<T>;
friend ostream& operator<< <>(const ostream&, const List<T>&);
friend ostream& operator<< <>(const ostream&, const Stack<T>&);
friend ostream& operator<< <>(const ostream&, const Queue<T>&);
};
template <typename T>
class List{
public:
friend ostream& operator<< <>(const ostream&, const List<T>&);
};
template <typename T>
class Stack{
public:
friend ostream& operator<< <>(const ostream&, const Stack<T>&);
};
template <typename T>
class Queue{
public:
friend ostream& operator<< <>(const ostream&, const Queue<T>&);
};
This is where the implementation comes into play, and I can't figure out the syntax.
template <typename T>
ostream& operator<<(const ostream& cout, const List<T>& toPrint){ <-- what do I change here?
// irrelevant body
}
template <typename T>
ostream& operator<<(const ostream& cout, const Stack<T>& toPrint){ <-- what do I change here?
// irrelevant body
}
template <typename T>
ostream& operator<<(const ostream& cout, const Queue<T>& toPrint){ <-- what do I change here?
// irrelevant body
}
What do I need to change in each of those three lines to make this work?
I keep getting compiler errors:
error: template-id ‘operator<< <>’ for ‘std::ostream& operator<<(const ostream&, const Queue<Card>&)’ does not match any template declaration
I guess it might be those:
friend ostream& operator<< <>(const ostream&, const List<T>&);
friend ostream& operator<< <>(const ostream&, const Stack<T>&);
friend ostream& operator<< <>(const ostream&, const Queue<T>&);
lines. You didn't specify the type of a template:
friend ostream& operator<< <T>(ostream&, const List<T>&);
friend ostream& operator<< <T>(ostream&, const Stack<T>&);
friend ostream& operator<< <T>(ostream&, const Queue<T>&);
so compiler couldn't match declarations with definitions.
So declarations:
friend ostream& operator<< <T>(const ostream&, const List<T>&);
and definitions:
template <typename T>
ostream& operator<<(ostream& cout, const List<T>& toPrint) {
// irrelevant body
}
Also to prevent compiler from complaining about not declared templates add declarations before class definition.
Final results:
#include <iostream>
using namespace std;
// Class delcarations - we need them to declare functions
template <typename T>
class List;
template <typename T>
class Stack;
template <typename T>
class Queue;
// operator<< function declaration informs compiler that there is function that can be befriended
template <typename T>
ostream& operator<<(ostream&, const List<T>&);
template <typename T>
ostream& operator<<(ostream&, const Stack<T>&);
template <typename T>
ostream& operator<<(ostream&, const Queue<T>&);
// Class definitions
template <typename T>
class Node{
private:
friend class List<T>;
friend class Stack<T>;
friend class Queue<T>;
};
template <typename T>
class List{
public:
friend ostream& operator<< <T>(ostream&, const List<T>&);
};
template <typename T>
class Stack{
public:
friend ostream& operator<< <T>(ostream&, const Stack<T>&);
};
template <typename T>
class Queue{
public:
friend ostream& operator<< <T>(ostream&, const Queue<T>&);
};
// Actual implemetations
template <typename T>
ostream& operator<<(ostream& out, const List<T>& toPrint) {
out << "List";
return cout;
}
template <typename T>
ostream& operator<<(ostream& out, const Stack<T>& toPrint) {
out << "Stack";
return out;
}
template <typename T>
ostream& operator<<(ostream& out, const Queue<T>& toPrint) {
out << "Queue";
return out;
}
// Template instantations test
int main() {
List<int> list;
Stack<int> stack;
Queue<int> queue;
cout << list << endl
<< stack << endl
<< queue << endl;
return 0;
}
for me it printed:
List
Stack
Queue
Here and here you have some nice examples.
EDIT: You were right, I made some mistakes. Corrected the answer to the working one.
there are some weird things here.
firstly the error message renders ostream differently, the fact that it qualifies the return value as std::ostream& and not the parameter parsed in seems a bit fishy - but it could be a red herring.
it is always a shame to see "using namespace std;". i consider the using keyword to be absolutely forbidden - so i have no idea what problems or changes this might cause. i simply suspect it is related.
now - to debug this properly i'd suggest replacing the operator and friend with regular function templates and breaking the access levels to allow that test (i.e. remove private etc.), then introduce each element one at a time until you find which part is actually causing the problem.