Defining operators for vectors of templates

I'm reading Programming Principles and Practice Using C++ first edition first printing book. This book is really hard for beginners but I have studied it until chapter 19 and should finish it!

I have a problem with a drill in chapter 19. Please look at it in the link below.
http://uploads.im/S0mun.png

I have written the following code for questions number 1 through 13 of that drill but I have problems with the question number 14 of it.
There is no guide/sample on/of it until this section of the book! So I don't know how to solve it. :(

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
using namespace std;

template <class T> class S {
public:
	T val;
	S(T v) { val = v; }
	T& operator[](int);
	const T& operator[](int) const;
};

//-----------------------------------------

template<class T> T& S<T>::operator[](int n) {  
	return val[n];
}

//---------------------------------------------------

template<class T> const T& S<T>::operator[](int n) const {  
	return val[n];
}

//--------------------------------------------------------

template <class T> istream& operator>>(istream& i_s, S<T>& v_i) {
	return i_s >> v_i.val;
}

//--------------------------------------------------

template <class T> ostream& operator<<(ostream& o_s, const S<T>& v_o) {
	return o_s << v_o.val;
}

//---------------------------------------

template <class T> ostream& operator<<(ostream& o_s, const S<vector<T>>& v_o) {
	return o_s << v_o.val;
}

//---------------------------------------

template<class T> void read_val(T& v) {
	cin >> v;
}

//-------------------------------

template<class T> void write_val(const T& v) {
	cout << v << '\n';
}

//-----------------------------------------

template<class T> void write_val(const vector <T>& v) {
	for(int i=0; i<v.size(); i++)
		cout << v[i] << ' ';
	cout << endl;
}

//------------------------------------

int main()  
{
	vector<int> vs;
	for(int i=0; i<5; i++)
		vs.push_back(i*i);

	S<int> s1(5); 
	S<char> s2('c');
	S<double> s3(5.25);
	S<string> s4("Template");
	S<vector<int>> s5(vs);
    
	write_val(s1);
	write_val(s5);
	
	return 0;

}


The program runs successfully until write_val(s1); but facing write_val(s5); I get this error:

Error 1 error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const Vector<T>' (or there is no acceptable conversion) c:\users\me\documents\visual studio 2012\projects\test1\test1\test1.cpp 39

Please don't use friend feature. I haven't learnt it and likely I will learn it in next chapters of the book. :)
Thanks in advance.
Last edited on
1
2
3
template <class T> ostream& operator<<(ostream& o_s, const S<vector<T>>& v_o) {
	return o_s << v_o.val;
}

As the error says, there is no version of operator<< which knows what to do with a vector<T>. Question 14 suggests that you define it (not for you to define it for const S<vector<T>>, although that would work with a different definition.)
As the error says, there is no version of operator<< which knows what to do with a vector<T>. Question 14 suggests that you define it (not for you to define it for const S<vector<T>>, although that would work with a different definition.)

Yes, you are right. But I had to do that.

Defining that operator this way:
1
2
3
template <class T> ostream& operator<<(ostream& o_s, vector<T>& v_o) {
	return o_s << v_o.val;
}

leads to an error saying: 'val' is not a member of 'Vector<T>'

And defining it like:
1
2
3
template <class T> ostream& operator<<(ostream& o_s, vector<T>& v_o) {
	return o_s << v_o;
}

leads to an Stack overflow run-time error.

Now what is your suggestion please, considering what that question wants?

Define it as if you are dealing with a vector (which you are) and not an instance of S<T> (which you aren't.)

1
2
3
4
5
6
7
8
template <class T> 
ostream& operator<<(ostream& o_s, vector<T>& v_o) 
{
    for (auto& element : v_o)
        o_s << element << '\n' ;

    return o_s;
}
Thank you very much cire! It works!

The loop you used is unfamiliar for me and it's because my book is a little old. I applied this:
1
2
3
4
5
template <class T> ostream& operator<<(ostream& o_s, const vector<T>& v_o) {
	for(int i=0; i<v_o.size(); i++)
		o_s << v_o[i] << ' ';
	return o_s;
}


And fortunately it worked. :)

Now at this stage, some other new question comes up in my mind! (I saw somewhere that one was reading a whole book on how to use templates in C++. Now I better figure out how massive that subject — the templates in C++ — can be.)

When I wrote this code (as I talked about it in my previous post):
1
2
3
template <class T> ostream& operator<<(ostream& o_s, vector<T>& v_o) {
	return o_s << v_o;
}


It caused an Stack overflow run-time error.
But when I wrote the above code (the one I have used the for loop), it does not cause an error! It's very odd for me! What is the reason please?

Last edited on
What is the reason please?
The stream operator was called recursively.
The stream operator was called recursively.

I know it's a recursive method. I meant why is this method a recursive one and causes that stack overflow error:
1
2
3
template <class T> ostream& operator<<(ostream& o_s, const vector<T>& v_o) {
	return o_s << v_o;
}

but this one is not a recursive method and works fine:
1
2
3
4
5
template <class T> ostream& operator<<(ostream& o_s, const vector<T>& v_o) {
	for(int i=0; i<v_o.size(); i++)
		o_s << v_o[i] << ' ';
	return o_s;
}

?

That is, why does that for loop make the method not be a recursive method and makes it work fine?
This:
1
2
3
template <class T> ostream& operator<<(ostream& o_s, const vector<T>& v_o) {
	return o_s << v_o;
}
can be written as:
1
2
3
template <class T> ostream& operator<<(ostream& o_s, const vector<T>& v_o) {
	return operator<<(o_s, v_o); // This calls itself
}
It permanently calls itself. Hence due to it recursive nature it generates a stack overflow. Nothing stops it from calling itself again and again.

While the second one is not recursive. It can be written as:
1
2
3
4
5
template <class T> ostream& operator<<(ostream& o_s, const vector<T>& v_o) {
	for(int i=0; i<v_o.size(); i++)
		operator<<(o_s, v_o[i]).operator<<(o_s, ' '); // The first operator is called with the type T (which cannot be the vector again)
	return o_s;
}
operator<<(o_s, v_o[i]).operator<<(o_s, ' '); // The first operator is called with the type T (which cannot be the vector again)


So since v_o[i] is not another vector (it's an int value and the output operator is pre-defined for int values) therefore, that overloaded method will not be called anymore. Is it right?

Another question: How to make those operator[]()s useful for that code? Whether I remove them or not, the code runs successfully!

Whether I remove them or not, the code runs successfully!
What code?
What code?

I meant these:
1
2
T& operator[](int);
const T& operator[](int) const;

with their definitions.

You don't use this operators hence they are ignored.
You don't use this operators hence they are ignored.

I have used the operator[] in:
template <class T> ostream& operator<<(ostream& o_s, const vector<T>& v_o)

It makes me confused. I don't know the above use belongs to them or it's the built-in use. I meant since the author has wanted us to add them, someway we should apply them.
Last edited on
std::vector has its own overload of operator[]. That is what you're using (here: v_o[i]), not your overloads.
std::vector has its own overload of operator[].

Yes and what is question for me is that why the author (the creator of C++) has wanted us to add them while adding them is useless!

I Thank both of you coder and cire very much for your help. Apparently this webside doesn't offer the rep feature so I don't know how to appreciate you guys for your useful helps :)
Yes and what is question for me is that why the author (the creator of C++) has wanted us to add them while adding them is useless!

From your image, it was intended to replace getter/setters which, indeed, doesn't make a whole lot of sense as you don't have a container to index. On the other hand, if he meant operator() that might be more reasonable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>

using namespace std;

template <class T> class S {
public:
    S(T v) : val(v) {}

    T& operator()() { return val; }
    const T& operator()() const { return val; }
    void operator()(const T& v) { val = v; }

private:
    T val;
};

template <class T> ostream& operator<<(ostream& o_s, const S<T>& v_o) {
    return o_s << v_o();
}

template <class T> ostream& operator<<(ostream& o_s, const vector<T>& v_o) {
    for (int i = 0; i < v_o.size(); ++i)
        o_s << v_o[i] << ' ';
    return o_s;
}

template<class T> void write_val(const T& v) {
    cout << v << '\n';
}

int main()
{
    vector<int> vs;
    for (int i = 0; i<5; i++)
        vs.push_back(i*i);

    S<int> s1(5);
    S<char> s2('c');
    S<double> s3(5.25);
    S<string> s4("Template");
    S<vector<int>> s5(vs);

    write_val(s1);
    write_val(s5);

    return 0;
}


Topic archived. No new replies allowed.