Chapter 18 Section 18.3.1 Copy constructor help needed in compiling

Pages: 12
In the PPP2 book, there's the following code for the custom vector class being implemented starting from Chapter 17, for a copy constructor:
1
2
3
4
5
6
vector:: vector(const vector& arg)
// allocate elements, then initialize them by copying
    :sz{arg.sz}, elem{new double[arg.sz]}
{
    copy(arg,arg+sz,elem); // std::copy(); see §B.5.2
}


I don't know how to define custom iterators. For further reference, here's the code I have so far:
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
82
83
84
// a very simplified vector of doubles (like vector<double>)
class vector
{
	int sz;											// the size
	double *elem;									// pointer to the first element (of type double)
public:
	vector(int s);
	vector(std::initializer_list<double> lst);
	//vector(const vector&);							// copy constructor: define copy
	vector &operator=(const vector &);				// copy assignment
	~vector() { delete[] elem; }
	int size() const { return sz; }					// return current size
	double get(int n) const { return elem[n]; }		// access: read
	void set(int n, double v) { elem[n] = v; }		// access: write

	class iterator : public std::iterator<std::forward_iterator_tag, double>
	{
		iterator &operator+(double);
		iterator &operator[](double);
	};
};

void print_v(const vector &v);

int main()
{
	vector v{ 1, 2, 3, 4, 5 };
	print_v(v);
	keep_window_open();
}

// constructor option 1: allocate s doubles
// store s in sz
// initialize elem with all zeroes
vector::vector(int s)
	: sz{ s },
	  elem{new double[s]}
{
	for (int i = 0; i < s; ++i)
	{
		elem[i] = 0;
	}
}

// constructor option 2: initialize vector with initializatin list
// sz and elem are the same;
// except sz is initialized to the size of the initializer list
vector::vector(std::initializer_list<double> lst)
	: sz{ lst.size() },
	  elem{ new double[sz] }
{
	std::copy(lst.begin(), lst.end(), elem);
}

vector &vector::operator=(const vector &a)
	// make this vector a copy of a
{
	double *p = new double[a.sz];
	std::copy(a.elem, a.elem + a.sz, elem);
	delete[] elem;
	elem = p;
	sz = a.sz;
	return *this;
}

/*vector::vector(const vector &arg)
	: sz{arg.size()},
	  elem{new double[arg.sz]}
{
	std::copy(arg, vector(arg + sz), elem);
}*/

void print_v(const vector &v)
{
	for (unsigned int i = 0; i < v.size(); ++i)
	{
		std::cout << v.get(i) << "\n";
	}
}

vector::iterator &vector::iterator::operator+(double val)
{
	
}


I tried to search on the web for how to overload the iterator I need, but I haven't found anything good.
Last edited on
> Copy constructor help needed in compiling
> I don't know how to define custom iterators.
Thread topics are for summarizing your question


> iterator &operator+(double);
stop and think what you are doing.
1
2
vector::iterator it = /*¿what?*/;
it + 3.14; //¿what does this do? also, somehow it modifies it 


think on what an iterator should be able to do and how to implement that.
for example, you may use it to traverse the container, so you need to be able to
- get a position
- increment its position
- figure out if you reach the end
- access the element in that position
for that you need to overload the operators
*it, it->, ++it, it++, it==jt, it not_eq jt
(may see that in http://www.cplusplus.com/reference/iterator/ForwardIterator/ )

now, ¿how do you track that position? One way is to maintain a pointer.
then the increment, dereference and comparison are based on that pointer.
1
2
3
4
5
6
7
iterator vector::begin(){
	return iterator(elem);
}

bool iterator::operator==(const iterator &b) const{
	return this->ptr == b.ptr;
}



here's an example implementation http://www.cplusplus.com/reference/iterator/iterator/
Last edited on
I keep getting errors about std::iterator_traits<vector> not having an iterator_category defined. So I need to know how to do that, too. I tried to read some articles, but I wasn't able to get what to do exactly. And to be able to get copy(arg,arg+sz,elem); to compile, I need to overload a move_iterator the vector class, right? How do I do that?

I probably don't need a full iterator class for it yet. Just a move_iterator and iterator_traits with an iterator_category. I need to get that call to std::copy() in the copy constructor to compile.
Last edited on
Could someone please tell me what I've done wrong? The vector I copied using the copy constructor isn't doing anything. The program exits after printing the original vector.

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Osman Zakir
// 9 / 1 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 17 Section 17.2
// Building a vector incrementally, to eventually get something almost equivalent to the standard library vector (std::vector)

#include <iostream>
#include <algorithm>
#include <iterator>
#include "../../cust_std_lib_facilities.h"

// a very simplified vector of doubles (like vector<double>)
class vector
{
	int sz;											// the size
	double *elem;									// pointer to the first element (of type double)
public:
	vector(int s);
	vector(std::initializer_list<double> lst);
	vector(const vector&);							// copy constructor: define copy
	vector(vector &&a);
	vector operator()(double val) { return val; }
	vector& operator=(vector&&);					// move assignment
	vector &operator=(const vector &);				// copy assignment
	~vector() { delete[] elem; }
	int size() const { return sz; }					// return current size
	double get(int n) const { return elem[n]; }		// access: read
	double &operator[](int n) { return elem[n]; }
	double operator[](int n) const { return elem[n]; }
	void set(int n, double v) { elem[n] = v; }		// access: write

	class iterator : public std::iterator<std::forward_iterator_tag, vector, std::ptrdiff_t, vector*, vector&>
	{
		vector *v;
		double *p;
		double d;
	public:
		iterator(double *x) :v{}, p{ x }, d{} {}
		iterator(const iterator &it) : v{}, p{ it.p }, d{} {}
		iterator() :v{}, p{ v->elem }, d{} {}
		iterator(vector *v) :v{ v }, p{}, d{} {}
		iterator(double d) : v{}, p{}, d{d} {}
		iterator &operator++() { ++p; return *this; }
		iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
		iterator operator()(vector *v) { return iterator(v); }
		bool operator==(const iterator &rhs) const { return p == rhs.p; }
		bool operator!=(const iterator &rhs) const { return p != rhs.p; }
		double &operator*() { return *p; }
	};

	iterator begin() { return iterator(elem); }
	iterator end() { return iterator(elem[size() - 1]); }
	iterator begin() const { return iterator(elem); }
	iterator end() const { return iterator(elem[size() - 1]); }
};

void print_v(const vector &v);

int main()
{
	vector v(10);
	for (int i = 0; i < v.size(); ++i)
	{
		v[i] = i;
		std::cout << v[i];
	}
	std::cin.clear();
	std::cout << '\n';
	vector v2 = v;
	for (int i = 0; i < v2.size(); ++i)
	{
		std::cout << v2[i] << '\n';
	}
	keep_window_open();
}

// constructor option 1: allocate s doubles
// store s in sz
// initialize elem with all zeroes
vector::vector(int s)
	: sz{ s },
	  elem{new double[s]}
{
	for (int i = 0; i < s; ++i)
	{
		elem[i] = 0;
	}
}

// constructor option 2: initialize vector with initializatin list
// sz and elem are the same;
// except sz is initialized to the size of the initializer list
vector::vector(std::initializer_list<double> lst)
	: sz{ lst.size() },
	  elem{ new double[sz] }
{
	std::copy(lst.begin(), lst.end(), elem);
}

vector &vector::operator=(const vector &a)
	// make this vector a copy of a
{
	double *p = new double[a.sz];
	std::copy(a.elem, a.elem + a.sz, elem);
	delete[] elem;
	elem = p;
	sz = a.sz;
	return *this;
}

vector::vector(const vector &arg)
	: sz{arg.size()},
	  elem{new double[arg.sz]}
{
	std::copy(arg.begin(), arg.end(), elem);
}

void print_v(const vector &v)
{
	for (unsigned int i = 0; i < v.size(); ++i)
	{
		std::cout << v[i] << "\n";
	}
}

vector::vector(vector &&a)
	: sz{a.sz}, elem{a.elem}
{
	a.sz = 0;
	a.elem = nullptr;
}

vector &vector::operator=(vector &&a)
{
	delete[] elem;			// deallocate old space
	elem = a.elem;			// copy a's elem and sz
	sz = a.sz;
	a.elem = nullptr;		// make a the empty vector
	a.sz = 0;
	return *this;
}
> And to be able to get copy(arg,arg+sz,elem); to compile, I need to overload a
> move_iterator the vector class, right?
copy(arg.elem, arg.elem+arg.sz, elem);


> The program exits after printing the original vector.
the program crashes when trying to copy the vector. (you need to read the symptoms)
the problem is that `vector::end()' is ill-defined, an iterator will never reach the `end()' state by incrementing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	class iterator : public std::iterator<std::forward_iterator_tag, vector, std::ptrdiff_t, vector*, vector&>
//if you don't know what the template parameters mean, ¿why do you random fill them?
	{
		vector *v; //¿what for?
		double *p; //¿what for?
		double d; //¿what for?
	public:
		iterator(double *x) :v{}, p{ x }, d{} {} //v and d not used
		iterator(const iterator &it) : v{}, p{ it.p }, d{} {} //¿so you only copy p?
		iterator() :v{}, p{ v->elem }, d{} {} //¿are you kidding me? ¿where is v pointing at?
		iterator(vector *v) :v{ v }, p{}, d{} {} //...
		iterator(double d) : v{}, p{}, d{d} {} //yet another constructor
		iterator &operator++() { ++p; return *this; }
		iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
		iterator operator()(vector *v) { return iterator(v); } //¿what?
		bool operator==(const iterator &rhs) const { return p == rhs.p; } //you only seem to care about p
		bool operator!=(const iterator &rhs) const { return p != rhs.p; }
		double &operator*() { return *p; }
	};

don't star coding right away, design on paper, think a little.
What do you expect me to do? I obviously don't know what I'm doing because defining iterators and iterator_traits is completely new to me. I'm also not at the place in the book where it talks about that yet. I just need to define a move iterator and operator+ so that the code in the copy constructor would compile. I just want to know how to get it to compile. That's all.
Here's the code as of right now:
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Osman Zakir
// 9 / 1 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 17 Section 17.2
// Building a vector incrementally, to eventually get something almost equivalent to the standard library vector (std::vector)

#include <iostream>
#include <algorithm>
#include <iterator>
#include "../../cust_std_lib_facilities.h"

// a very simplified vector of doubles (like vector<double>)
class vector
{
	int sz;											// the size
	double *elem;									// pointer to the first element (of type double)
public:
	vector(int s);
	vector(std::initializer_list<double> lst);
	vector(const vector&);							// copy constructor: define copy
	vector(vector &&a);
	vector operator()(double val) { return val; }
	vector& operator=(vector&&);					// move assignment
	vector &operator=(const vector &);				// copy assignment
	vector operator+(int) const;
	~vector() { delete[] elem; }
	int size() const { return sz; }					// return current size
	double get(int n) const { return elem[n]; }		// access: read
	double &operator[](int n) { return elem[n]; }
	double operator[](int n) const { return elem[n]; }
	void set(int n, double v) { elem[n] = v; }		// access: write

	template<typename T>
	class iterator : public std::iterator<std::bidirectional_iterator_tag, T, std::ptrdiff_t, T*, T&>
	{
		template<typename T>
		class iterator_traits : std::iterator_traits<T>
		{
			typedef typename T::difference_type             difference_type;
			typedef typename T::value_type                  value_type;
			typedef typename T::pointer                     pointer_type;
			typedef typename T::reference                   reference_type;
			typedef typename T::iterator_category           iterator_category;
		};
		
		template<class Iterator>
		std::move_iterator<Iterator> make_move_iterator(Iterator i)
		{
			return std::move_iterator<Iterator>(i);
		}
	};

	template<typename T>
	iterator<T> begin() { return iterator<T>(elem); }
	template<typename T>
	iterator<T> end() { return iterator<T>(elem[size() - 1]); }
	template<typename T>
	iterator<T> begin() const { return iterator<T>(elem); }
	template<typename T>
	iterator<T> end() const { return iterator<T>(elem[size() - 1]); }
};

void print_v(const vector &v);

int main()
{
	vector v(10);
	for (int i = 0; i < v.size(); ++i)
	{
		v[i] = i;
		std::cout << v[i];
	}
	std::cin.clear();
	std::cout << '\n';
	vector v2 = v;
	for (int i = 0; i < v2.size(); ++i)
	{
		std::cout << v2[i] << '\n';
	}
	keep_window_open();
}

// constructor option 1: allocate s doubles
// store s in sz
// initialize elem with all zeroes
vector::vector(int s)
	: sz{ s },
	  elem{new double[s]}
{
	for (int i = 0; i < s; ++i)
	{
		elem[i] = 0;
	}
}

// constructor option 2: initialize vector with initializatin list
// sz and elem are the same;
// except sz is initialized to the size of the initializer list
vector::vector(std::initializer_list<double> lst)
	: sz{ lst.size() },
	  elem{ new double[sz] }
{
	std::copy(lst.begin(), lst.end(), elem);
}

vector &vector::operator=(const vector &a)
	// make this vector a copy of a
{
	double *p = new double[a.sz];
	std::copy(a.elem, a.elem + a.sz, elem);
	delete[] elem;
	elem = p;
	sz = a.sz;
	return *this;
}

vector::vector(const vector &arg)
	: sz{arg.size()},
	  elem{new double[arg.sz]}
{
	std::copy(arg, arg + sz, elem);
}

void print_v(const vector &v)
{
	for (unsigned int i = 0; i < v.size(); ++i)
	{
		std::cout << v[i] << "\n";
	}
}

vector::vector(vector &&a)
	: sz{a.sz}, elem{a.elem}
{
	a.sz = 0;
	a.elem = nullptr;
}

vector &vector::operator=(vector &&a)
{
	delete[] elem;			// deallocate old space
	elem = a.elem;			// copy a's elem and sz
	sz = a.sz;
	a.elem = nullptr;		// make a the empty vector
	a.sz = 0;
	return *this;
}

vector vector::operator+(int i) const
{
	while (i > 0 && i < sz)
	{
		*this + i;
	}
	return *this;
}


The error I get when trying to compile it is
no type named 'iterator_category' in 'std::iterator_traits<vector>'
Last edited on
What do you expect me to do?

Read the book would be my first suggestion.

Stop jumping ahead of yourself would be my second suggestion, iterators are covered in a later chapter.

Read the answer I posted in your other thread about this topic would be my third suggestion. (To restate that answer: You don't need an iterator, you need to create a copy() member function to copy the required values.)
How do get rid of this compiler error?
no type named 'iterator_category' in 'std::iterator_traits<vector>'


Also, how do I create that copy() member function? Will it take away that error message?
Also, how do I create that copy() member function?

It's in the book, read it for yourself.

Will it take away that error message?

Yes because it's not using an iterator, read the book.



I tried to define an operator+ without an iterator, and it still gave me that error. I'll try it again.

Like I thought, I still get the same errors as before:
Here's the Build output:
1>------ Build started: Project: custom_vector, Configuration: Debug Win32 ------
1>custom_vector.cpp
1>In file included from custom_vector.cpp:7:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\iostream:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\istream:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\ostream:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\ios:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xlocnum:10:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\streambuf:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xiosbase:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xlocale:8:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\stdexcept:7:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xstring:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xmemory0:10:
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(641,2): error : no type named 'iterator_category' in 'std::iterator_traits<vector>'
1> using _Iter_cat_t = typename iterator_traits<_Iter>::iterator_category;
1> ^~~~~
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(984,45) : note: in instantiation of template type alias '_Iter_cat_t' requested here
1> _Debug_range2(_First, _Last, _File, _Line, _Iter_cat_t<_InIt>());
1> ^
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(2281,2) : note: in instantiation of function template specialization 'std::_Debug_range<vector>' requested here
1> _DEBUG_RANGE(_First, _Last);
1> ^
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(931,2) : note: expanded from macro '_DEBUG_RANGE'
1> _DEBUG_RANGE_IMPL(first, last, _FILENAME, __LINE__)
1> ^
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(927,30) : note: expanded from macro '_DEBUG_RANGE_IMPL'
1> #define _DEBUG_RANGE_IMPL _Debug_range
1> ^
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(2295,10) : note: in instantiation of function template specialization 'std::_Copy_no_deprecate<vector, double *>' requested here
1> return (_Copy_no_deprecate(_First, _Last, _Dest));
1> ^
1>custom_vector.cpp(92,7) : note: in instantiation of function template specialization 'std::copy<vector, double *>' requested here
1> std::copy(arg, arg + sz, elem);
1> ^
1>In file included from custom_vector.cpp:7:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\iostream:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\istream:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\ostream:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\ios:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xlocnum:10:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\streambuf:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xiosbase:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xlocale:8:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\stdexcept:7:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xstring:6:
1>In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xmemory0:10:
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(641,2): error : no type named 'iterator_category' in 'std::iterator_traits<vector>'
1> using _Iter_cat_t = typename iterator_traits<_Iter>::iterator_category;
1> ^~~~~
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(689,50) : note: in instantiation of template type alias '_Iter_cat_t' requested here
1> return (_Idl_distance1<_Checked>(_First, _Last, _Iter_cat_t<_Iter>()));
1> ^
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(2284,42) : note: in instantiation of function template specialization 'std::_Idl_distance<vector, vector>' requested here
1> const auto _UDest = _Unchecked_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast));
1> ^
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\xutility(2295,10) : note: in instantiation of function template specialization 'std::_Copy_no_deprecate<vector, double *>' requested here
1> return (_Copy_no_deprecate(_First, _Last, _Dest));
1> ^
1>custom_vector.cpp(92,7) : note: in instantiation of function template specialization 'std::copy<vector, double *>' requested here
1> std::copy(arg, arg + sz, elem);
1> ^
1>2 errors generated.
1>Done building project "custom_vector.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


Here's the copy constructor:
1
2
3
4
5
6
vector::vector(const vector &arg)
	: sz{arg.size()},
	  elem{new double[arg.sz]}
{
	std::copy(arg, arg + sz, elem);
}
As it is in the book.

And here's the operator+ (which might be wrong):
1
2
3
4
5
6
7
8
vector vector::operator+(int i) const
{
	while (i > 0 && i < sz)
	{
		*this + i;
	}
	return *this;
}
Last edited on
Here's the full code:
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Osman Zakir
// 9 / 1 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 17 Section 17.2
// Building a vector incrementally, to eventually get something almost equivalent to the standard library vector (std::vector)

#include <iostream>
#include <algorithm>#include "../../cust_std_lib_facilities.h"

// a very simplified vector of doubles (like vector<double>)
class vector
{
	int sz;											// the size
	double *elem;									// pointer to the first element (of type double)
public:
	vector(int s);
	vector(std::initializer_list<double> lst);
	vector(const vector&);							// copy constructor: define copy
	vector(vector &&a);
	vector& operator=(vector&&);					// move assignment
	vector &operator=(const vector &);				// copy assignment
	vector operator+(int) const;
	~vector() { delete[] elem; }
	int size() const { return sz; }					// return current size
	double get(int n) const { return elem[n]; }		// access: read
	double &operator[](int n) { return elem[n]; }
	double operator[](int n) const { return elem[n]; }
	void set(int n, double v) { elem[n] = v; }		// access: write
};

void print_v(const vector &v);

int main()
{
	vector v(10);
	for (int i = 0; i < v.size(); ++i)
	{
		v[i] = i;
		std::cout << v[i];
	}
	std::cin.clear();
	std::cout << '\n';
	vector v2 = v;
	for (int i = 0; i < v2.size(); ++i)
	{
		std::cout << v2[i] << '\n';
	}
	keep_window_open();
}

// constructor option 1: allocate s doubles
// store s in sz
// initialize elem with all zeroes
vector::vector(int s)
	: sz{ s },
	  elem{new double[s]}
{
	for (int i = 0; i < s; ++i)
	{
		elem[i] = 0;
	}
}

// constructor option 2: initialize vector with initializatin list
// sz and elem are the same;
// except sz is initialized to the size of the initializer list
vector::vector(std::initializer_list<double> lst)
	: sz{ lst.size() },
	  elem{ new double[sz] }
{
	std::copy(lst.begin(), lst.end(), elem);
}

vector &vector::operator=(const vector &a)
	// make this vector a copy of a
{
	double *p = new double[a.sz];
	std::copy(a.elem, a.elem + a.sz, elem);
	delete[] elem;
	elem = p;
	sz = a.sz;
	return *this;
}

vector::vector(const vector &arg)
	: sz{arg.size()},
	  elem{new double[arg.sz]}
{
	std::copy(arg, arg + sz, elem);
}

void print_v(const vector &v)
{
	for (unsigned int i = 0; i < v.size(); ++i)
	{
		std::cout << v[i] << "\n";
	}
}

vector::vector(vector &&a)
	: sz{a.sz}, elem{a.elem}
{
	a.sz = 0;
	a.elem = nullptr;
}

vector &vector::operator=(vector &&a)
{
	delete[] elem;			// deallocate old space
	elem = a.elem;			// copy a's elem and sz
	sz = a.sz;
	a.elem = nullptr;		// make a the empty vector
	a.sz = 0;
	return *this;
}

vector vector::operator+(int i) const
{
	while (i > 0 && i < sz)
	{
		*this + i;
	}
	return *this;
}
Last edited on
What is line 123 supposed to be doing?

The whole point of the operator+ is that it's supposed to define what it means to add i to this. So simply writing *this + i isn't going to work, because you still havent defined what that means.

The operator needs to define how a vector object changes when you add i to it.

Also, even if that *this + i calculation did make sense, line 123 would calculate something and then throw the result away. It's the equivalent of just writing:

 
  a + b;  // what happens to the result of this calculation? 
Last edited on
How do I tell it what it means, then?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
vector &vector::operator=(const vector &a)
	// make this vector a copy of a
{
	double *p = new double[a.sz];
	std::copy(a.elem, a.elem + a.sz, elem); //look at this 
	delete[] elem;
	elem = p;
	sz = a.sz;
	return *this;
}

vector::vector(const vector &arg)
	: sz{arg.size()},
	  elem{new double[arg.sz]}
{
	std::copy(arg, arg + sz, elem); //compare against this
}

you could also do a loop
I got both of those from the book as is. I haven't changed it. This is the copy constructor straight from the book - compare it:
1
2
3
4
5
6
vector::vector(const vector& arg)
// allocate elements, then initialize them by copying
    :sz{arg.sz}, elem{new double[arg.sz]}
{
    copy(arg,arg+sz,elem); // std::copy(); see §B.5.2
}


I just want to know how to correctly overload that operator.
I would say that's a typo on the book.
note the types involved
copy( vector, vector+int, double* );
`vector+int' makes no semantic sense.
same as the whole idea of using a vector as an iterator.

It should be copy(arg.elem, arg.elem+arg.sz, elem);
How do I tell it what it means, then?

You write the code that implements what this + i means in the operator+ method. How does adding an integer to a vector change that vector? Write the code that makes that change.

What does it mean to add an integer to a vector? Can you answer that question?
It should mean the position of the vector index is updated up to as many times as the value of the integer passed into the operator function.

Something like this?
1
2
3
4
5
6
7
vector vector::operator+(int i) const
{
    vector temp{};
    temp[0] = temp[0] + i;
    *this = temp;
    return *this;
}


Edit: @ne555's tip helped. It worked when I did:
1
2
3
4
5
6
vector::vector(const vector &arg)
	: sz{arg.size()},
	  elem{new double[arg.sz]}
{
	std::copy(arg.elem, arg.elem + arg.sz, elem);
}


Thanks.
Last edited on
1
2
3
4
5
6
7
vector vector::operator+(int i) const
{
    vector temp{};
    temp[0] = temp[0] + i;
    *this = temp;
    return *this;
}

Can you talk me through what you think that code is doing, step by step? Because, as it stands, it doesn't make much sense, and I think it would be helpful to identify what it is you've misunderstood.
Last edited on
Pages: 12