17
17
#include < vector>
18
18
19
19
#include " count_new.h"
20
+ #include " exception_test_helpers.h"
21
+ #include " test_allocator.h"
20
22
#include " test_iterators.h"
21
23
22
- template <class T >
23
- struct Allocator {
24
- using value_type = T;
25
- using is_always_equal = std::false_type;
26
-
27
- template <class U >
28
- Allocator (const Allocator<U>&) {}
29
-
30
- Allocator (bool should_throw = true ) {
31
- if (should_throw)
32
- throw 0 ;
33
- }
34
-
35
- T* allocate (std::size_t n) { return std::allocator<T>().allocate (n); }
36
- void deallocate (T* ptr, std::size_t n) { std::allocator<T>().deallocate (ptr, n); }
37
-
38
- template <class U >
39
- friend bool operator ==(const Allocator&, const Allocator<U>&) { return true ; }
40
- };
41
-
42
- struct ThrowingT {
43
- int * throw_after_n_ = nullptr ;
44
- ThrowingT () { throw 0 ; }
45
-
46
- ThrowingT (int & throw_after_n) : throw_after_n_(&throw_after_n) {
47
- if (throw_after_n == 0 )
48
- throw 0 ;
49
- --throw_after_n;
50
- }
51
-
52
- ThrowingT (const ThrowingT& rhs) : throw_after_n_(rhs.throw_after_n_) {
53
- if (throw_after_n_ == nullptr || *throw_after_n_ == 0 )
54
- throw 1 ;
55
- --*throw_after_n_;
56
- }
57
-
58
- ThrowingT& operator =(const ThrowingT& rhs) {
59
- throw_after_n_ = rhs.throw_after_n_ ;
60
- if (throw_after_n_ == nullptr || *throw_after_n_ == 0 )
61
- throw 1 ;
62
- --*throw_after_n_;
63
- return *this ;
64
- }
65
- };
66
-
67
- template <class IterCat >
68
- struct Iterator {
69
- using iterator_category = IterCat;
70
- using difference_type = std::ptrdiff_t ;
71
- using value_type = int ;
72
- using reference = int &;
73
- using pointer = int *;
74
-
75
- int i_;
76
- Iterator (int i = 0 ) : i_(i) {}
77
- int & operator *() {
78
- if (i_ == 1 )
79
- throw 1 ;
80
- return i_;
81
- }
82
-
83
- friend bool operator ==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_ ; }
84
-
85
- friend bool operator !=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_ ; }
86
-
87
- Iterator& operator ++() {
88
- ++i_;
89
- return *this ;
90
- }
91
-
92
- Iterator operator ++(int ) {
93
- auto tmp = *this ;
94
- ++i_;
95
- return tmp;
96
- }
97
- };
98
-
99
- void check_new_delete_called () {
100
- assert (globalMemCounter.new_called == globalMemCounter.delete_called );
101
- assert (globalMemCounter.new_array_called == globalMemCounter.delete_array_called );
102
- assert (globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called );
103
- assert (globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called );
104
- }
105
-
106
24
int main (int , char **) {
107
- using AllocVec = std::vector<int , Allocator <int > >;
25
+ using AllocVec = std::vector<int , throwing_allocator <int > >;
108
26
try { // vector()
109
27
AllocVec vec;
110
28
} catch (int ) {
111
29
}
112
30
check_new_delete_called ();
113
31
114
32
try { // Throw in vector(size_type) from type
115
- std::vector<ThrowingT > get_alloc (1 );
33
+ std::vector<throwing_t > get_alloc (1 );
116
34
} catch (int ) {
117
35
}
118
36
check_new_delete_called ();
119
37
120
38
#if TEST_STD_VER >= 14
121
39
try { // Throw in vector(size_type, value_type) from type
122
40
int throw_after = 1 ;
123
- ThrowingT v (throw_after);
124
- std::vector<ThrowingT > get_alloc (1 , v);
41
+ throwing_t v (throw_after);
42
+ std::vector<throwing_t > get_alloc (1 , v);
125
43
} catch (int ) {
126
44
}
127
45
check_new_delete_called ();
128
46
129
- try { // Throw in vector(size_type, const allocator_type&) from allocator
130
- Allocator <int > alloc (false );
47
+ try { // Throw in vector(size_type, const allocator_type&) from allocator
48
+ throwing_allocator <int > alloc (false , true ); // throw on copy only
131
49
AllocVec get_alloc (0 , alloc);
132
50
} catch (int ) {
133
51
}
134
52
check_new_delete_called ();
135
53
136
54
try { // Throw in vector(size_type, const allocator_type&) from the type
137
- std::vector<ThrowingT > vec (1 , std::allocator<ThrowingT >());
55
+ std::vector<throwing_t > vec (1 , std::allocator<throwing_t >());
138
56
} catch (int ) {
139
57
}
140
58
check_new_delete_called ();
141
- #endif // TEST_STD_VER >= 14
59
+ #endif // TEST_STD_VER >= 14
142
60
143
61
try { // Throw in vector(size_type, value_type, const allocator_type&) from the type
144
62
int throw_after = 1 ;
145
- ThrowingT v (throw_after);
146
- std::vector<ThrowingT > vec (1 , v, std::allocator<ThrowingT >());
63
+ throwing_t v (throw_after);
64
+ std::vector<throwing_t > vec (1 , v, std::allocator<throwing_t >());
147
65
} catch (int ) {
148
66
}
149
67
check_new_delete_called ();
150
68
151
69
try { // Throw in vector(InputIterator, InputIterator) from input iterator
152
- std::vector<int > vec ((Iterator<std::input_iterator_tag>()), Iterator<std::input_iterator_tag>(2 ));
70
+ std::vector<int > vec (
71
+ (throwing_iterator<int , std::input_iterator_tag>()), throwing_iterator<int , std::input_iterator_tag>(2 ));
153
72
} catch (int ) {
154
73
}
155
74
check_new_delete_called ();
156
75
157
76
try { // Throw in vector(InputIterator, InputIterator) from forward iterator
158
- std::vector<int > vec ((Iterator<std::forward_iterator_tag>()), Iterator<std::forward_iterator_tag>(2 ));
77
+ std::vector<int > vec (
78
+ (throwing_iterator<int , std::forward_iterator_tag>()), throwing_iterator<int , std::forward_iterator_tag>(2 ));
159
79
} catch (int ) {
160
80
}
161
81
check_new_delete_called ();
@@ -169,21 +89,24 @@ int main(int, char**) {
169
89
170
90
try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator
171
91
std::allocator<int > alloc;
172
- std::vector<int > vec (Iterator<std::input_iterator_tag>(), Iterator<std::input_iterator_tag>(2 ), alloc);
92
+ std::vector<int > vec (
93
+ throwing_iterator<int , std::input_iterator_tag>(), throwing_iterator<int , std::input_iterator_tag>(2 ), alloc);
173
94
} catch (int ) {
174
95
}
175
96
check_new_delete_called ();
176
97
177
98
try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator
178
99
std::allocator<int > alloc;
179
- std::vector<int > vec (Iterator<std::forward_iterator_tag>(), Iterator<std::forward_iterator_tag>(2 ), alloc);
100
+ std::vector<int > vec (throwing_iterator<int , std::forward_iterator_tag>(),
101
+ throwing_iterator<int , std::forward_iterator_tag>(2 ),
102
+ alloc);
180
103
} catch (int ) {
181
104
}
182
105
check_new_delete_called ();
183
106
184
107
try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
185
108
int a[] = {1 , 2 };
186
- Allocator <int > alloc (false );
109
+ throwing_allocator <int > alloc (false , true ); // throw on copy only
187
110
AllocVec vec (cpp17_input_iterator<int *>(a), cpp17_input_iterator<int *>(a + 2 ), alloc);
188
111
} catch (int ) {
189
112
// FIXME: never called.
@@ -192,51 +115,52 @@ int main(int, char**) {
192
115
193
116
try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
194
117
int a[] = {1 , 2 };
195
- Allocator <int > alloc (false );
118
+ throwing_allocator <int > alloc (false , true ); // throw on copy only
196
119
AllocVec vec (forward_iterator<int *>(a), forward_iterator<int *>(a + 2 ), alloc);
197
120
} catch (int ) {
198
121
// FIXME: never called.
199
122
}
200
123
check_new_delete_called ();
201
124
202
125
try { // Throw in vector(const vector&) from type
203
- std::vector<ThrowingT > vec;
204
- int throw_after = 0 ;
126
+ std::vector<throwing_t > vec;
127
+ int throw_after = 1 ;
205
128
vec.emplace_back (throw_after);
206
129
auto vec2 = vec;
207
130
} catch (int ) {
208
131
}
209
132
check_new_delete_called ();
210
133
211
134
try { // Throw in vector(const vector&, const allocator_type&) from type
212
- std::vector<ThrowingT > vec;
135
+ std::vector<throwing_t > vec;
213
136
int throw_after = 1 ;
214
137
vec.emplace_back (throw_after);
215
- std::vector<ThrowingT > vec2 (vec, std::allocator<int >());
138
+ std::vector<throwing_t > vec2 (vec, std::allocator<int >());
216
139
} catch (int ) {
217
140
}
218
141
check_new_delete_called ();
219
142
220
- try { // Throw in vector(vector&&, const allocator_type&) from type
221
- std::vector<ThrowingT, Allocator<ThrowingT> > vec (Allocator<ThrowingT>(false ));
222
- int throw_after = 1 ;
223
- vec.emplace_back (throw_after);
224
- std::vector<ThrowingT, Allocator<ThrowingT> > vec2 (std::move (vec), Allocator<ThrowingT>(false ));
143
+ try { // Throw in vector(vector&&, const allocator_type&) from type during element-wise move
144
+ std::vector<throwing_t , test_allocator<throwing_t > > vec (test_allocator<throwing_t >(1 ));
145
+ int throw_after = 10 ;
146
+ throwing_t v (throw_after);
147
+ vec.insert (vec.end (), 6 , v);
148
+ std::vector<throwing_t , test_allocator<throwing_t > > vec2 (std::move (vec), test_allocator<throwing_t >(2 ));
225
149
} catch (int ) {
226
150
}
227
151
check_new_delete_called ();
228
152
229
153
#if TEST_STD_VER >= 11
230
154
try { // Throw in vector(initializer_list<value_type>) from type
231
155
int throw_after = 1 ;
232
- std::vector<ThrowingT > vec ({ThrowingT (throw_after)});
156
+ std::vector<throwing_t > vec ({throwing_t (throw_after)});
233
157
} catch (int ) {
234
158
}
235
159
check_new_delete_called ();
236
160
237
161
try { // Throw in vector(initializer_list<value_type>, const allocator_type&) constructor from type
238
162
int throw_after = 1 ;
239
- std::vector<ThrowingT > vec ({ThrowingT (throw_after)}, std::allocator<ThrowingT >());
163
+ std::vector<throwing_t > vec ({throwing_t (throw_after)}, std::allocator<throwing_t >());
240
164
} catch (int ) {
241
165
}
242
166
check_new_delete_called ();
0 commit comments