Skip to content

Commit 5ce981e

Browse files
authored
[libc++] Refactor vector move constructor with allocator (#116449)
This PR simplifies the implementation of std::vector's move constructor with an alternative allocator by invoking __init_with_size() instead of calling assign(), which ultimately calls __assign_with_size(). The advantage of using __init_with_size() lies in its internal use of an exception guard, which simplifies the code. Furthermore, from a semantic standpoint, it is more intuitive for a constructor to call an initialization function than an assignment function.
1 parent cefc1b0 commit 5ce981e

File tree

2 files changed

+12
-10
lines changed

2 files changed

+12
-10
lines changed

libcxx/include/__vector/vector.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -964,9 +964,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
964964
__x.__begin_ = __x.__end_ = __x.__cap_ = nullptr;
965965
} else {
966966
typedef move_iterator<iterator> _Ip;
967-
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
968-
assign(_Ip(__x.begin()), _Ip(__x.end()));
969-
__guard.__complete();
967+
__init_with_size(_Ip(__x.begin()), _Ip(__x.end()), __x.size());
970968
}
971969
}
972970

libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <vector>
1818

1919
#include "count_new.h"
20+
#include "test_allocator.h"
2021
#include "test_iterators.h"
2122

2223
template <class T>
@@ -36,7 +37,9 @@ struct Allocator {
3637
void deallocate(T* ptr, std::size_t n) { std::allocator<T>().deallocate(ptr, n); }
3738

3839
template <class U>
39-
friend bool operator==(const Allocator&, const Allocator<U>&) { return true; }
40+
friend bool operator==(const Allocator&, const Allocator<U>&) {
41+
return true;
42+
}
4043
};
4144

4245
struct ThrowingT {
@@ -138,7 +141,7 @@ int main(int, char**) {
138141
} catch (int) {
139142
}
140143
check_new_delete_called();
141-
#endif // TEST_STD_VER >= 14
144+
#endif // TEST_STD_VER >= 14
142145

143146
try { // Throw in vector(size_type, value_type, const allocator_type&) from the type
144147
int throw_after = 1;
@@ -217,11 +220,12 @@ int main(int, char**) {
217220
}
218221
check_new_delete_called();
219222

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));
223+
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));
225+
int throw_after = 10;
226+
ThrowingT v(throw_after);
227+
vec.insert(vec.end(), 6, v);
228+
std::vector<ThrowingT, test_allocator<ThrowingT> > vec2(std::move(vec), test_allocator<ThrowingT>(2));
225229
} catch (int) {
226230
}
227231
check_new_delete_called();

0 commit comments

Comments
 (0)