1616#include < type_traits>
1717#include < vector>
1818
19+ #include " ../common.h"
1920#include " count_new.h"
2021#include " test_allocator.h"
2122#include " test_iterators.h"
2223
23- template <class T >
24- struct Allocator {
25- using value_type = T;
26- using is_always_equal = std::false_type;
27-
28- template <class U >
29- Allocator (const Allocator<U>&) {}
30-
31- Allocator (bool should_throw = true ) {
32- if (should_throw)
33- throw 0 ;
34- }
35-
36- T* allocate (std::size_t n) { return std::allocator<T>().allocate (n); }
37- void deallocate (T* ptr, std::size_t n) { std::allocator<T>().deallocate (ptr, n); }
38-
39- template <class U >
40- friend bool operator ==(const Allocator&, const Allocator<U>&) {
41- return true ;
42- }
43- };
44-
45- struct ThrowingT {
46- int * throw_after_n_ = nullptr ;
47- ThrowingT () { throw 0 ; }
48-
49- ThrowingT (int & throw_after_n) : throw_after_n_(&throw_after_n) {
50- if (throw_after_n == 0 )
51- throw 0 ;
52- --throw_after_n;
53- }
54-
55- ThrowingT (const ThrowingT& rhs) : throw_after_n_(rhs.throw_after_n_) {
56- if (throw_after_n_ == nullptr || *throw_after_n_ == 0 )
57- throw 1 ;
58- --*throw_after_n_;
59- }
60-
61- ThrowingT& operator =(const ThrowingT& rhs) {
62- throw_after_n_ = rhs.throw_after_n_ ;
63- if (throw_after_n_ == nullptr || *throw_after_n_ == 0 )
64- throw 1 ;
65- --*throw_after_n_;
66- return *this ;
67- }
68- };
69-
70- template <class IterCat >
71- struct Iterator {
72- using iterator_category = IterCat;
73- using difference_type = std::ptrdiff_t ;
74- using value_type = int ;
75- using reference = int &;
76- using pointer = int *;
77-
78- int i_;
79- Iterator (int i = 0 ) : i_(i) {}
80- int & operator *() {
81- if (i_ == 1 )
82- throw 1 ;
83- return i_;
84- }
85-
86- friend bool operator ==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_ ; }
87-
88- friend bool operator !=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_ ; }
89-
90- Iterator& operator ++() {
91- ++i_;
92- return *this ;
93- }
94-
95- Iterator operator ++(int ) {
96- auto tmp = *this ;
97- ++i_;
98- return tmp;
99- }
100- };
101-
102- void check_new_delete_called () {
103- assert (globalMemCounter.new_called == globalMemCounter.delete_called );
104- assert (globalMemCounter.new_array_called == globalMemCounter.delete_array_called );
105- assert (globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called );
106- assert (globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called );
107- }
108-
10924int main (int , char **) {
110- using AllocVec = std::vector<int , Allocator <int > >;
25+ using AllocVec = std::vector<int , throwing_allocator <int > >;
11126 try { // vector()
11227 AllocVec vec;
11328 } catch (int ) {
11429 }
11530 check_new_delete_called ();
11631
11732 try { // Throw in vector(size_type) from type
118- std::vector<ThrowingT > get_alloc (1 );
33+ std::vector<throwing_t > get_alloc (1 );
11934 } catch (int ) {
12035 }
12136 check_new_delete_called ();
12237
12338#if TEST_STD_VER >= 14
12439 try { // Throw in vector(size_type, value_type) from type
12540 int throw_after = 1 ;
126- ThrowingT v (throw_after);
127- std::vector<ThrowingT > get_alloc (1 , v);
41+ throwing_t v (throw_after);
42+ std::vector<throwing_t > get_alloc (1 , v);
12843 } catch (int ) {
12944 }
13045 check_new_delete_called ();
13146
132- try { // Throw in vector(size_type, const allocator_type&) from allocator
133- 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
13449 AllocVec get_alloc (0 , alloc);
13550 } catch (int ) {
13651 }
13752 check_new_delete_called ();
13853
13954 try { // Throw in vector(size_type, const allocator_type&) from the type
140- std::vector<ThrowingT > vec (1 , std::allocator<ThrowingT >());
55+ std::vector<throwing_t > vec (1 , std::allocator<throwing_t >());
14156 } catch (int ) {
14257 }
14358 check_new_delete_called ();
14459#endif // TEST_STD_VER >= 14
14560
14661 try { // Throw in vector(size_type, value_type, const allocator_type&) from the type
14762 int throw_after = 1 ;
148- ThrowingT v (throw_after);
149- 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 >());
15065 } catch (int ) {
15166 }
15267 check_new_delete_called ();
15368
15469 try { // Throw in vector(InputIterator, InputIterator) from input iterator
155- 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 ));
15672 } catch (int ) {
15773 }
15874 check_new_delete_called ();
15975
16076 try { // Throw in vector(InputIterator, InputIterator) from forward iterator
161- 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 ));
16279 } catch (int ) {
16380 }
16481 check_new_delete_called ();
@@ -172,21 +89,24 @@ int main(int, char**) {
17289
17390 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator
17491 std::allocator<int > alloc;
175- 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);
17694 } catch (int ) {
17795 }
17896 check_new_delete_called ();
17997
18098 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator
18199 std::allocator<int > alloc;
182- 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);
183103 } catch (int ) {
184104 }
185105 check_new_delete_called ();
186106
187107 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
188108 int a[] = {1 , 2 };
189- Allocator <int > alloc (false );
109+ throwing_allocator <int > alloc (false , true ); // throw on copy only
190110 AllocVec vec (cpp17_input_iterator<int *>(a), cpp17_input_iterator<int *>(a + 2 ), alloc);
191111 } catch (int ) {
192112 // FIXME: never called.
@@ -195,52 +115,52 @@ int main(int, char**) {
195115
196116 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
197117 int a[] = {1 , 2 };
198- Allocator <int > alloc (false );
118+ throwing_allocator <int > alloc (false , true ); // throw on copy only
199119 AllocVec vec (forward_iterator<int *>(a), forward_iterator<int *>(a + 2 ), alloc);
200120 } catch (int ) {
201121 // FIXME: never called.
202122 }
203123 check_new_delete_called ();
204124
205125 try { // Throw in vector(const vector&) from type
206- std::vector<ThrowingT > vec;
207- int throw_after = 0 ;
126+ std::vector<throwing_t > vec;
127+ int throw_after = 1 ;
208128 vec.emplace_back (throw_after);
209129 auto vec2 = vec;
210130 } catch (int ) {
211131 }
212132 check_new_delete_called ();
213133
214134 try { // Throw in vector(const vector&, const allocator_type&) from type
215- std::vector<ThrowingT > vec;
135+ std::vector<throwing_t > vec;
216136 int throw_after = 1 ;
217137 vec.emplace_back (throw_after);
218- std::vector<ThrowingT > vec2 (vec, std::allocator<int >());
138+ std::vector<throwing_t > vec2 (vec, std::allocator<int >());
219139 } catch (int ) {
220140 }
221141 check_new_delete_called ();
222142
223143 try { // Throw in vector(vector&&, const allocator_type&) from type during element-wise move
224- std::vector<ThrowingT , test_allocator<ThrowingT > > vec (test_allocator<ThrowingT >(1 ));
144+ std::vector<throwing_t , test_allocator<throwing_t > > vec (test_allocator<throwing_t >(1 ));
225145 int throw_after = 10 ;
226- ThrowingT v (throw_after);
146+ throwing_t v (throw_after);
227147 vec.insert (vec.end (), 6 , v);
228- std::vector<ThrowingT , test_allocator<ThrowingT > > vec2 (std::move (vec), test_allocator<ThrowingT >(2 ));
148+ std::vector<throwing_t , test_allocator<throwing_t > > vec2 (std::move (vec), test_allocator<throwing_t >(2 ));
229149 } catch (int ) {
230150 }
231151 check_new_delete_called ();
232152
233153#if TEST_STD_VER >= 11
234154 try { // Throw in vector(initializer_list<value_type>) from type
235155 int throw_after = 1 ;
236- std::vector<ThrowingT > vec ({ThrowingT (throw_after)});
156+ std::vector<throwing_t > vec ({throwing_t (throw_after)});
237157 } catch (int ) {
238158 }
239159 check_new_delete_called ();
240160
241161 try { // Throw in vector(initializer_list<value_type>, const allocator_type&) constructor from type
242162 int throw_after = 1 ;
243- std::vector<ThrowingT > vec ({ThrowingT (throw_after)}, std::allocator<ThrowingT >());
163+ std::vector<throwing_t > vec ({throwing_t (throw_after)}, std::allocator<throwing_t >());
244164 } catch (int ) {
245165 }
246166 check_new_delete_called ();
0 commit comments