Posts tagged ostream
Overloading << and >> for template functions in C++
0You probably know that the ostream and istream operators (<< and >>) can be overloaded for your custom classes, but let's take a look at how to overload them for template classes like the vector class.
Overloading for template functions
The way this is done is by placing the keyword template before the function. After template we have to specify the type, or we can use a generic type T. Let me illustrate this with an example:
// Overloading for a template of type int. For example vector<int> template<int> myFunction(){} // Overloading for any type template<typename T> myFunction(){}
Alright so now that you know how to overload a template function, let's see how to overload them for the ostream and istream operators.
For this example I will assume we are working with the STL Vector library, and the way I will modify the operators is the following:
- For the ostream operator (<<) I will display first the size of the vector and then it's elements
- For the istream operator (>>) I will ask first for the size and then each of it's elements.
Let's see those functions:
template<typename T> ostream & operator < <(ostream & o,vector<T> & v){ int s = v.size(); o < < s << endl; for(int i=0;i<s;i++){ o << v[i] << endl; } return o; } template<typename T> istream & operator >>(istream & i,vector<t> & v){ int s; i >> s; T holder; for(int a=0;a<s ;a++){ i >> holder; v.push_back(holder); } return i; }
The only thing to take into account here is the holder variable I have created in the istream overloaded operator. Instead of directly using i >> v[a]; because that would throw an error, I created a variable holder of type T (The same as the vector) and then we "hold" the vector element before adding it to the vector v.
Notice that in the istream operator we don't create the vector and then return it, because we already have it's reference in v. We use push_back because v could have no elements.
In practice:
Let me show you a rather simple main using this two operators with two vectors of type int and float to show you that it works with any type of data.
#include <iostream> #include <vector> using namespace std; template<typename T> ostream & operator < <(ostream & o,vector<T> & v){ int s = v.size(); o < < s << endl; for(int i=0;i<s;i++){ o << v[i] << endl; } return o; } template<typename T> istream & operator >>(istream & i,vector<t> & v){ int s; i >> s; T holder; for(int a=0;a<s ;a++){ i >> holder; v.push_back(holder); } return i; } int main(){ // Creamos dos vectores a y b vector<int> a; vector<float> b; // Usando el operador sobrecargado de extraccion les damos valores: cout < < "Please enter the size of a vector of integers, then its elements: "; cin >> a; cout < < "\nNow the same with floats for another vector: "; cin >> b; // Y finalmente los mostramos por pantalla: cout < < "\nThe values of both vectors (First the size then the elements): "; cout << "\nIntegers: " << a << "\nFloating point: " << b; cin.get();cin.get(); return 0; }
Overloading input/output operators C++
1As you might know, when we develop a simple program that runs in the system console, using the standard library iostream, we might want to have special ways of displaying a class object.
You have probably heard of the istream and ostream operators (<< and >>), we can use overloading to change their behaviour.
Since they are not functions from our class, we must use a special keyword, friend. A friend function is neither public or private, our class doesn't control it's scope. They are classes that don't belong to a class, but have access to its private members.
Let's create a simple class to demonstrate this:
class simple{ int a,b; public: friend ostream & operator < <(ostream & o, simple & s){ o << s.a << " " << s.b; return o; } friend istream & operator >>(istream & i, simple & s){ i >> s.a >> s.b; return i; } };
This class has two private members, a and b. I haven't created any constructors as we don't really need them for the example. We will change the values of a and b using the input operator >> and we will display them using the output operator <<
How the istream and ostream operators work is quite simple actually. Declaring them friend gives them direct access to private members a and b. But since they don't belong to the class we must pass them a reference to the object from the class simple we want to modify: simple & s. The other parameter is the reference to the i/o stream itself, all our modifications will be "stored" in that reference and then returned.
Let me show you a basic main to show it in use:
main(){ simple obj; cin >> obj; cout < < "\nDisplay my simple object: "; cout << obj << endl; system("pause"); return 0; }
In this sample main we instantiate simple in the object obj, and we then call the input operator >> to give a and b some values.
After that we display the values using the output operator <<.
This simple program generates the following output (Imagine I enter 2 and 3 as input):
2 3 Display my simple object: 2 3
If you want the full working code:
#include <iostream> using namespace std; class simple{ int a,b; public: friend ostream & operator < <(ostream & o, simple & s){ o << s.a << " " << s.b; return o; } friend istream & operator >>(istream & i, simple & s){ i >> s.a >> s.b; return i; } }; main(){ simple obj; cin >> obj; cout < < "\nDisplay my simple object: "; cout << obj << endl; system("pause"); return 0; }
Well I hope you enjoyed this and understood it correctly
If you have any problems or suggestions feel free to comment below,
Alex