1717#include < vector>
1818
1919#include " count_new.h"
20+ #include " exception_test_helpers.h"
21+ #include " test_allocator.h"
2022#include " test_iterators.h"
2123
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-
10624int main (int , char **) {
107- using AllocVec = std::vector<int , Allocator <int > >;
25+ using AllocVec = std::vector<int , throwing_allocator <int > >;
10826 try { // vector()
10927 AllocVec vec;
11028 } catch (int ) {
11129 }
11230 check_new_delete_called ();
11331
11432 try { // Throw in vector(size_type) from type
115- std::vector<ThrowingT > get_alloc (1 );
33+ std::vector<throwing_t > get_alloc (1 );
11634 } catch (int ) {
11735 }
11836 check_new_delete_called ();
11937
12038#if TEST_STD_VER >= 14
12139 try { // Throw in vector(size_type, value_type) from type
12240 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);
12543 } catch (int ) {
12644 }
12745 check_new_delete_called ();
12846
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
13149 AllocVec get_alloc (0 , alloc);
13250 } catch (int ) {
13351 }
13452 check_new_delete_called ();
13553
13654 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 >());
13856 } catch (int ) {
13957 }
14058 check_new_delete_called ();
141- #endif // TEST_STD_VER >= 14
59+ #endif // TEST_STD_VER >= 14
14260
14361 try { // Throw in vector(size_type, value_type, const allocator_type&) from the type
14462 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 >());
14765 } catch (int ) {
14866 }
14967 check_new_delete_called ();
15068
15169 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 ));
15372 } catch (int ) {
15473 }
15574 check_new_delete_called ();
15675
15776 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 ));
15979 } catch (int ) {
16080 }
16181 check_new_delete_called ();
@@ -169,21 +89,24 @@ int main(int, char**) {
16989
17090 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator
17191 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);
17394 } catch (int ) {
17495 }
17596 check_new_delete_called ();
17697
17798 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator
17899 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);
180103 } catch (int ) {
181104 }
182105 check_new_delete_called ();
183106
184107 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
185108 int a[] = {1 , 2 };
186- Allocator <int > alloc (false );
109+ throwing_allocator <int > alloc (false , true ); // throw on copy only
187110 AllocVec vec (cpp17_input_iterator<int *>(a), cpp17_input_iterator<int *>(a + 2 ), alloc);
188111 } catch (int ) {
189112 // FIXME: never called.
@@ -192,51 +115,52 @@ int main(int, char**) {
192115
193116 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
194117 int a[] = {1 , 2 };
195- Allocator <int > alloc (false );
118+ throwing_allocator <int > alloc (false , true ); // throw on copy only
196119 AllocVec vec (forward_iterator<int *>(a), forward_iterator<int *>(a + 2 ), alloc);
197120 } catch (int ) {
198121 // FIXME: never called.
199122 }
200123 check_new_delete_called ();
201124
202125 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 ;
205128 vec.emplace_back (throw_after);
206129 auto vec2 = vec;
207130 } catch (int ) {
208131 }
209132 check_new_delete_called ();
210133
211134 try { // Throw in vector(const vector&, const allocator_type&) from type
212- std::vector<ThrowingT > vec;
135+ std::vector<throwing_t > vec;
213136 int throw_after = 1 ;
214137 vec.emplace_back (throw_after);
215- std::vector<ThrowingT > vec2 (vec, std::allocator<int >());
138+ std::vector<throwing_t > vec2 (vec, std::allocator<int >());
216139 } catch (int ) {
217140 }
218141 check_new_delete_called ();
219142
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 ));
225149 } catch (int ) {
226150 }
227151 check_new_delete_called ();
228152
229153#if TEST_STD_VER >= 11
230154 try { // Throw in vector(initializer_list<value_type>) from type
231155 int throw_after = 1 ;
232- std::vector<ThrowingT > vec ({ThrowingT (throw_after)});
156+ std::vector<throwing_t > vec ({throwing_t (throw_after)});
233157 } catch (int ) {
234158 }
235159 check_new_delete_called ();
236160
237161 try { // Throw in vector(initializer_list<value_type>, const allocator_type&) constructor from type
238162 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 >());
240164 } catch (int ) {
241165 }
242166 check_new_delete_called ();
0 commit comments