11
11
// iterator erase(const_iterator position);
12
12
13
13
#include < vector>
14
- #include < iterator>
15
14
#include < cassert>
15
+ #include < memory>
16
16
17
17
#include " asan_testing.h"
18
+ #include " common.h"
18
19
#include " min_allocator.h"
19
20
#include " MoveOnly.h"
20
21
#include " test_macros.h"
21
22
22
- #ifndef TEST_HAS_NO_EXCEPTIONS
23
- struct Throws {
24
- Throws () : v_(0 ) {}
25
- Throws (int v) : v_(v) {}
26
- Throws (const Throws& rhs) : v_(rhs.v_) {
27
- if (sThrows )
28
- throw 1 ;
29
- }
30
- Throws (Throws&& rhs) : v_(rhs.v_) {
31
- if (sThrows )
32
- throw 1 ;
33
- }
34
- Throws& operator =(const Throws& rhs) {
35
- v_ = rhs.v_ ;
36
- return *this ;
37
- }
38
- Throws& operator =(Throws&& rhs) {
39
- v_ = rhs.v_ ;
40
- return *this ;
41
- }
42
- int v_;
43
- static bool sThrows ;
44
- };
45
-
46
- bool Throws::sThrows = false ;
47
- #endif
48
-
49
- TEST_CONSTEXPR_CXX20 bool tests () {
50
- {
51
- int a1[] = {1 , 2 , 3 , 4 , 5 };
52
- std::vector<int > l1 (a1, a1 + 5 );
53
- l1.erase (l1.begin ());
54
- assert (is_contiguous_container_asan_correct (l1));
55
- assert (l1 == std::vector<int >(a1 + 1 , a1 + 5 ));
56
- }
23
+ template <template <class > class Allocator , class T >
24
+ TEST_CONSTEXPR_CXX20 void tests () {
57
25
{
58
- int a1[] = {1 , 2 , 3 , 4 , 5 };
59
- int e1 [] = {1 , 3 , 4 , 5 };
60
- std::vector<int > l1 (a1, a1 + 5 );
61
- l1.erase (l1.begin () + 1 );
62
- assert (is_contiguous_container_asan_correct (l1));
63
- assert (l1 == std::vector<int >(e1 , e1 + 4 ));
64
- }
65
- {
66
- int a1[] = {1 , 2 , 3 };
67
- std::vector<int > l1 (a1, a1 + 3 );
68
- std::vector<int >::const_iterator i = l1.begin ();
69
- assert (is_contiguous_container_asan_correct (l1));
70
- ++i;
71
- std::vector<int >::iterator j = l1.erase (i);
72
- assert (l1.size () == 2 );
73
- assert (std::distance (l1.begin (), l1.end ()) == 2 );
74
- assert (*j == 3 );
75
- assert (*l1.begin () == 1 );
76
- assert (*std::next (l1.begin ()) == 3 );
77
- assert (is_contiguous_container_asan_correct (l1));
78
- j = l1.erase (j);
79
- assert (j == l1.end ());
80
- assert (l1.size () == 1 );
81
- assert (std::distance (l1.begin (), l1.end ()) == 1 );
82
- assert (*l1.begin () == 1 );
83
- assert (is_contiguous_container_asan_correct (l1));
84
- j = l1.erase (l1.begin ());
85
- assert (j == l1.end ());
86
- assert (l1.size () == 0 );
87
- assert (std::distance (l1.begin (), l1.end ()) == 0 );
88
- assert (is_contiguous_container_asan_correct (l1));
89
- }
26
+ T arr[] = {T (1 ), T (2 ), T (3 ), T (4 ), T (5 )};
27
+ using Vector = std::vector<T, Allocator<T> >;
28
+ using Iterator = typename Vector::iterator;
90
29
91
- // Make sure vector::erase works with move-only types
92
- // When non-trivial
93
- {
94
- std::vector<MoveOnly> v;
95
- v.emplace_back (1 );
96
- v.emplace_back (2 );
97
- v.emplace_back (3 );
98
- v.erase (v.begin ());
99
- assert (v.size () == 2 );
100
- assert (v[0 ] == MoveOnly (2 ));
101
- assert (v[1 ] == MoveOnly (3 ));
102
- }
103
- // When trivial
104
- {
105
- std::vector<TrivialMoveOnly> v;
106
- v.emplace_back (1 );
107
- v.emplace_back (2 );
108
- v.emplace_back (3 );
109
- v.erase (v.begin ());
110
- assert (v.size () == 2 );
111
- assert (v[0 ] == TrivialMoveOnly (2 ));
112
- assert (v[1 ] == TrivialMoveOnly (3 ));
30
+ {
31
+ Vector v (arr, arr + 5 );
32
+ Iterator it = v.erase (v.cbegin ());
33
+ assert (v == Vector (arr + 1 , arr + 5 ));
34
+ assert (it == v.begin ());
35
+ assert (is_contiguous_container_asan_correct (v));
36
+ }
37
+ {
38
+ T expected[] = {T (1 ), T (3 ), T (4 ), T (5 )};
39
+ Vector v (arr, arr + 5 );
40
+ Iterator it = v.erase (v.cbegin () + 1 );
41
+ assert (v == Vector (expected, expected + 4 ));
42
+ assert (it == v.begin () + 1 );
43
+ assert (is_contiguous_container_asan_correct (v));
44
+ }
45
+ {
46
+ T expected[] = {T (1 ), T (2 ), T (3 ), T (4 )};
47
+ Vector v (arr, arr + 5 );
48
+ Iterator it = v.erase (v.cbegin () + 4 );
49
+ assert (v == Vector (expected, expected + 4 ));
50
+ assert (it == v.end ());
51
+ assert (is_contiguous_container_asan_correct (v));
52
+ }
113
53
}
114
54
115
- # if TEST_STD_VER >= 11
55
+ // Make sure vector::erase works with move-only types
116
56
{
117
- int a1[] = {1 , 2 , 3 };
118
- std::vector<int , min_allocator<int >> l1 (a1, a1 + 3 );
119
- std::vector<int , min_allocator<int >>::const_iterator i = l1.begin ();
120
- assert (is_contiguous_container_asan_correct (l1));
121
- ++i;
122
- std::vector<int , min_allocator<int >>::iterator j = l1.erase (i);
123
- assert (l1.size () == 2 );
124
- assert (std::distance (l1.begin (), l1.end ()) == 2 );
125
- assert (*j == 3 );
126
- assert (*l1.begin () == 1 );
127
- assert (*std::next (l1.begin ()) == 3 );
128
- assert (is_contiguous_container_asan_correct (l1));
129
- j = l1.erase (j);
130
- assert (j == l1.end ());
131
- assert (l1.size () == 1 );
132
- assert (std::distance (l1.begin (), l1.end ()) == 1 );
133
- assert (*l1.begin () == 1 );
134
- assert (is_contiguous_container_asan_correct (l1));
135
- j = l1.erase (l1.begin ());
136
- assert (j == l1.end ());
137
- assert (l1.size () == 0 );
138
- assert (std::distance (l1.begin (), l1.end ()) == 0 );
139
- assert (is_contiguous_container_asan_correct (l1));
57
+ // When non-trivial
58
+ {
59
+ std::vector<MoveOnly, Allocator<MoveOnly> > v;
60
+ v.emplace_back (1 );
61
+ v.emplace_back (2 );
62
+ v.emplace_back (3 );
63
+ v.erase (v.begin ());
64
+ assert (v.size () == 2 );
65
+ assert (v[0 ] == MoveOnly (2 ));
66
+ assert (v[1 ] == MoveOnly (3 ));
67
+ }
68
+ // When trivial
69
+ {
70
+ std::vector<TrivialMoveOnly, Allocator<TrivialMoveOnly> > v;
71
+ v.emplace_back (1 );
72
+ v.emplace_back (2 );
73
+ v.emplace_back (3 );
74
+ v.erase (v.begin ());
75
+ assert (v.size () == 2 );
76
+ assert (v[0 ] == TrivialMoveOnly (2 ));
77
+ assert (v[1 ] == TrivialMoveOnly (3 ));
78
+ }
140
79
}
141
- # endif
80
+ }
142
81
82
+ TEST_CONSTEXPR_CXX20 bool tests () {
83
+ tests<std::allocator, int >();
84
+ tests<std::allocator, NonTriviallyRelocatable>();
85
+ tests<min_allocator, int >();
86
+ tests<min_allocator, NonTriviallyRelocatable>();
143
87
return true ;
144
88
}
145
89
@@ -163,5 +107,31 @@ int main(int, char**) {
163
107
}
164
108
#endif
165
109
110
+ // Make sure we satisfy the complexity requirement in terms of the number of times the assignment
111
+ // operator is called.
112
+ //
113
+ // There is currently ambiguity as to whether this is truly mandated by the Standard, so we only
114
+ // test it for libc++.
115
+ #ifdef _LIBCPP_VERSION
116
+ {
117
+ Tracker tracker;
118
+ std::vector<TrackedAssignment> v;
119
+
120
+ // Set up the vector with 5 elements.
121
+ for (int i = 0 ; i != 5 ; ++i) {
122
+ v.emplace_back (&tracker);
123
+ }
124
+ assert (tracker.copy_assignments == 0 );
125
+ assert (tracker.move_assignments == 0 );
126
+
127
+ // Erase element [1] from it. Elements [2] [3] [4] should be shifted, so we should
128
+ // see 3 move assignments (and nothing else).
129
+ v.erase (v.begin () + 1 );
130
+ assert (v.size () == 4 );
131
+ assert (tracker.copy_assignments == 0 );
132
+ assert (tracker.move_assignments == 3 );
133
+ }
134
+ #endif
135
+
166
136
return 0 ;
167
137
}
0 commit comments