1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// <vector>
10
11// iterator erase(const_iterator position);
12
13#include <vector>
14#include <cassert>
15#include <memory>
16
17#include "asan_testing.h"
18#include "common.h"
19#include "min_allocator.h"
20#include "MoveOnly.h"
21#include "test_macros.h"
22
23template <template <class> class Allocator, class T>
24TEST_CONSTEXPR_CXX20 void tests() {
25 {
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;
29
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 }
53 }
54
55 // Make sure vector::erase works with move-only types
56 {
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 }
79 }
80}
81
82TEST_CONSTEXPR_CXX20 bool tests() {
83 tests<std::allocator, int>();
84 tests<std::allocator, NonTriviallyRelocatable>();
85 tests<min_allocator, int>();
86 tests<min_allocator, NonTriviallyRelocatable>();
87 return true;
88}
89
90int main(int, char**) {
91 tests();
92#if TEST_STD_VER > 17
93 static_assert(tests());
94#endif
95
96#ifndef TEST_HAS_NO_EXCEPTIONS
97 // Test for LWG2853:
98 // Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T.
99 {
100 Throws arr[] = {1, 2, 3};
101 std::vector<Throws> v(arr, arr + 3);
102 Throws::sThrows = true;
103 v.erase(position: v.begin());
104 v.erase(position: --v.end());
105 v.erase(position: v.begin());
106 assert(v.size() == 0);
107 }
108#endif
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
136 return 0;
137}
138

source code of libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp