forked from chihyang/CPP_Primer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExer16_29_Blob.h
More file actions
171 lines (171 loc) · 5.24 KB
/
Copy pathExer16_29_Blob.h
File metadata and controls
171 lines (171 loc) · 5.24 KB
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Note: this header has an unsolved problem. See notes below.
#ifndef EXER16_29_BLOB_H
#define EXER16_29_BLOB_H
#include <string>
#include <vector>
#include <initializer_list>
#include <utility>
#include <stdexcept>
#include "Exer16_28_shared_ptr.h"
// #include <memory> // must be excluded, see notes below.
template <typename T> class BlobPtr;
template <typename T> class ConstBlobPtr;
template <typename T> class Blob;
template <typename T> bool operator==(const Blob<T>&, const Blob<T>&);
template <typename T> bool operator!=(const Blob<T>&, const Blob<T>&);
template <typename T> bool operator<(const Blob<T>&, const Blob<T>&);
template <typename T> bool operator<=(const Blob<T>&, const Blob<T>&);
template <typename T> bool operator>(const Blob<T>&, const Blob<T>&);
template <typename T> bool operator>=(const Blob<T>&, const Blob<T>&);
template <typename T> class Blob {
friend class BlobPtr<T>;
friend bool operator==<T>(const Blob<T>&, const Blob<T>&);
friend bool operator!=<T>(const Blob<T>&, const Blob<T>&);
friend bool operator< <T>(const Blob<T>&, const Blob<T>&);
friend bool operator<=<T>(const Blob<T>&, const Blob<T>&);
friend bool operator><T>(const Blob<T>&, const Blob<T>&);
friend bool operator>=<T>(const Blob<T>&, const Blob<T>&);
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
typedef typename std::vector<T>::difference_type difference_type;
// constructors
Blob();
Blob(std::initializer_list<T> il);
// template member function required by exercise 16.24
template <typename It> Blob(It b, It e);
// size
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
// elements
void push_back(const T &t) { data->push_back(t); }
void push_back(T &&t) { data->push_back(std::move(t)); }
void pop_back();
T& front();
T& back();
// const version from exercise 12.2
const T& front() const;
const T& back() const;
T& operator[] (size_type);
const T& operator[] (size_type) const;
T& at(size_type);
const T& at(size_type) const;
// use count
size_type use_count() const { return data->use_count(); }
private:
shared_ptr<std::vector<T>> data;
void check(size_type, const std::string&) const;
};
// constructors
template <typename T>
Blob<T>::Blob(): data(make_shared<std::vector<T>>()) {}
template <typename T>
Blob<T>::Blob(std::initializer_list<T> il): data(make_shared<std::vector<T>>(il)) {}
template <typename T>
template <typename It>
Blob<T>::Blob(It b, It e) : data(make_shared<std::vector<T>>(b, e)) {}
// check index
template <typename T>
void Blob<T>::check(size_type i, const std::string &msg) const
{
if(i >= data->size())
throw std::out_of_range(msg);
}
// add and remove elements
template <typename T>
void Blob<T>::pop_back()
{
check(0, "pop_back on empty Blob");
data->pop_back();
}
// element access
template <typename T>
T& Blob<T>::front()
{
check(0, "front on empty Blob");
data->front();
}
template <typename T>
T& Blob<T>::back()
{
check(0, "back on empty Blob");
data->back();
}
template <typename T>
const T& Blob<T>::front() const
{
check(0, "front on empty Blob");
data->front();
}
template <typename T>
const T& Blob<T>::back() const
{
check(0, "back on empty Blob");
data->back();
}
template <typename T>
T& Blob<T>::operator[](size_type i)
{
check(i, "index out of range");
return (*data)[i];
}
template <typename T>
const T& Blob<T>::operator[](size_type i) const
{
check(i, "index out of range");
return (*data)[i];
}
template <typename T>
T& Blob<T>::at(size_type i)
{
check(i, "index out of range");
return data->at(i);
}
template <typename T>
const T& Blob<T>::at(size_type i) const
{
check(i, "index out of range");
return data->at(i);
}
// relational operators
template <typename T>
inline bool operator==(const Blob<T> &lhs, const Blob<T> &rhs)
{
return *lhs.data == *rhs.data;
}
template <typename T>
inline bool operator!=(const Blob<T> &lhs, const Blob<T> &rhs)
{
return !(lhs == rhs);
}
template <typename T>
inline bool operator<(const Blob<T> &lhs, const Blob<T> &rhs)
{
return *lhs.data < *rhs.data;
}
template <typename T>
inline bool operator<=(const Blob<T> &lhs, const Blob<T> &rhs)
{
return (lhs < rhs || lhs == rhs);
}
template <typename T>
inline bool operator>(const Blob<T> &lhs, const Blob<T> &rhs)
{
return !(lhs < rhs || lhs == rhs);
}
template <typename T>
inline bool operator>=(const Blob<T> &lhs, const Blob<T> &rhs)
{
return !(lhs < rhs);
}
#endif
// Note: the header <memory> must be excluded, or even if we don't use std:: before
// make_shared, the program still uses standard library version of it. THE REASON
// IS NOT KNOWN FOR NOW.
// The result is that even if <memory> is after "Exer16_28_shared_ptr.h", still
// the standard library version of make_shared is used. But shared_ptr must
// follow std:: if we want to use the standard library version. Here we don't want
// to use the standard library version so we don't use std::; now the problem
// emerges: (std::)make_shared can only work with std::shared_ptr, but we provide
// a custom version of shared_ptr. As a result, the program won't compile. So we
// had better not include memory here.