Skip to content

Commit 26c107e

Browse files
committed
swap
1 parent 0a50e30 commit 26c107e

File tree

6 files changed

+427
-333
lines changed

6 files changed

+427
-333
lines changed

libcxx/include/variant

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1586,7 +1586,7 @@ visit(_Visitor&& __visitor, _Vs&&... __vs) {
15861586
# endif
15871587

15881588
template <class... _Types>
1589-
_LIBCPP_HIDE_FROM_ABI auto
1589+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 auto
15901590
swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs) noexcept(noexcept(__lhs.swap(__rhs)))
15911591
-> decltype(__lhs.swap(__rhs)) {
15921592
return __lhs.swap(__rhs);

libcxx/test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -590,22 +590,52 @@ void test_assignment_throw() {
590590
#endif // TEST_HAS_NO_EXCEPTIONS
591591
}
592592

593-
template <std::size_t NewIdx, class ValueType>
594-
constexpr bool test_constexpr_assign_imp(std::variant<long, void*, int>&& v, ValueType&& new_value) {
595-
const std::variant<long, void*, int> cp(std::forward<ValueType>(new_value));
593+
template <std::size_t NewIdx, class T, class ValueType>
594+
constexpr void test_constexpr_assign_imp(T&& v, ValueType&& new_value) {
595+
using Variant = std::decay_t<T>;
596+
const Variant cp(std::forward<ValueType>(new_value));
596597
v = cp;
597-
return v.index() == NewIdx && std::get<NewIdx>(v) == std::get<NewIdx>(cp);
598+
assert(v.index() == NewIdx);
599+
assert(std::get<NewIdx>(v) == std::get<NewIdx>(cp));
598600
}
599601

600-
void test_constexpr_copy_assignment() {
602+
constexpr bool test_constexpr_copy_assignment_trivial() {
601603
// Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
602604
using V = std::variant<long, void*, int>;
603605
static_assert(std::is_trivially_copyable<V>::value, "");
604606
static_assert(std::is_trivially_copy_assignable<V>::value, "");
605-
static_assert(test_constexpr_assign_imp<0>(V(42l), 101l), "");
606-
static_assert(test_constexpr_assign_imp<0>(V(nullptr), 101l), "");
607-
static_assert(test_constexpr_assign_imp<1>(V(42l), nullptr), "");
608-
static_assert(test_constexpr_assign_imp<2>(V(42l), 101), "");
607+
test_constexpr_assign_imp<0>(V(42l), 101l);
608+
test_constexpr_assign_imp<0>(V(nullptr), 101l);
609+
test_constexpr_assign_imp<1>(V(42l), nullptr);
610+
test_constexpr_assign_imp<2>(V(42l), 101);
611+
612+
return true;
613+
}
614+
615+
struct NonTrivialCopyAssign {
616+
int i = 0;
617+
constexpr NonTrivialCopyAssign(int ii) : i(ii) {}
618+
constexpr NonTrivialCopyAssign(const NonTrivialCopyAssign& other) : i(other.i) {}
619+
constexpr NonTrivialCopyAssign& operator=(const NonTrivialCopyAssign& o) {
620+
i = o.i;
621+
return *this;
622+
}
623+
TEST_CONSTEXPR_CXX20 ~NonTrivialCopyAssign() = default;
624+
friend constexpr bool operator==(const NonTrivialCopyAssign& x, const NonTrivialCopyAssign& y) { return x.i == y.i; }
625+
};
626+
627+
constexpr bool test_constexpr_copy_assignment_non_trivial() {
628+
// Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
629+
using V = std::variant<long, void*, NonTrivialCopyAssign>;
630+
static_assert(!std::is_trivially_copyable<V>::value, "");
631+
static_assert(!std::is_trivially_copy_assignable<V>::value, "");
632+
test_constexpr_assign_imp<0>(V(42l), 101l);
633+
test_constexpr_assign_imp<0>(V(nullptr), 101l);
634+
test_constexpr_assign_imp<1>(V(42l), nullptr);
635+
test_constexpr_assign_imp<2>(V(42l), NonTrivialCopyAssign(5));
636+
test_constexpr_assign_imp<2>(V(NonTrivialCopyAssign(3)), NonTrivialCopyAssign(5));
637+
638+
return true;
609639
}
610640

611641
int main(int, char**) {
@@ -617,11 +647,14 @@ int main(int, char**) {
617647
test_copy_assignment_different_index();
618648
test_copy_assignment_sfinae();
619649
test_copy_assignment_not_noexcept();
620-
test_constexpr_copy_assignment();
650+
test_constexpr_copy_assignment_trivial();
651+
test_constexpr_copy_assignment_non_trivial();
621652

653+
static_assert(test_constexpr_copy_assignment_trivial());
622654
#if TEST_STD_VER >= 20
623655
static_assert(test_copy_assignment_same_index());
624656
static_assert(test_copy_assignment_different_index());
657+
static_assert(test_constexpr_copy_assignment_non_trivial());
625658
#endif
626659

627660
return 0;

libcxx/test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -470,23 +470,54 @@ void test_assignment_throw() {
470470
#endif // TEST_HAS_NO_EXCEPTIONS
471471
}
472472

473-
template <std::size_t NewIdx, class ValueType>
474-
constexpr bool test_constexpr_assign_imp(std::variant<long, void*, int>&& v, ValueType&& new_value) {
475-
std::variant<long, void*, int> v2(std::forward<ValueType>(new_value));
473+
template <std::size_t NewIdx, class T, class ValueType>
474+
constexpr void test_constexpr_assign_imp(T&& v, ValueType&& new_value) {
475+
using Variant = std::decay_t<T>;
476+
Variant v2(std::forward<ValueType>(new_value));
476477
const auto cp = v2;
477478
v = std::move(v2);
478-
return v.index() == NewIdx && std::get<NewIdx>(v) == std::get<NewIdx>(cp);
479+
assert(v.index() == NewIdx);
480+
assert(std::get<NewIdx>(v) == std::get<NewIdx>(cp));
479481
}
480482

481-
void test_constexpr_move_assignment() {
483+
constexpr bool test_constexpr_move_assignment_trivial() {
482484
// Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
483485
using V = std::variant<long, void*, int>;
484486
static_assert(std::is_trivially_copyable<V>::value, "");
485487
static_assert(std::is_trivially_move_assignable<V>::value, "");
486-
static_assert(test_constexpr_assign_imp<0>(V(42l), 101l), "");
487-
static_assert(test_constexpr_assign_imp<0>(V(nullptr), 101l), "");
488-
static_assert(test_constexpr_assign_imp<1>(V(42l), nullptr), "");
489-
static_assert(test_constexpr_assign_imp<2>(V(42l), 101), "");
488+
test_constexpr_assign_imp<0>(V(42l), 101l);
489+
test_constexpr_assign_imp<0>(V(nullptr), 101l);
490+
test_constexpr_assign_imp<1>(V(42l), nullptr);
491+
test_constexpr_assign_imp<2>(V(42l), 101);
492+
493+
return true;
494+
}
495+
496+
struct NonTrivialMoveAssign {
497+
int i = 0;
498+
constexpr NonTrivialMoveAssign(int ii) : i(ii) {}
499+
constexpr NonTrivialMoveAssign(const NonTrivialMoveAssign& other) = default;
500+
constexpr NonTrivialMoveAssign(NonTrivialMoveAssign&& other) : i(other.i) {}
501+
constexpr NonTrivialMoveAssign& operator=(const NonTrivialMoveAssign&) = default;
502+
constexpr NonTrivialMoveAssign& operator=(NonTrivialMoveAssign&& o) {
503+
i = o.i;
504+
return *this;
505+
}
506+
TEST_CONSTEXPR_CXX20 ~NonTrivialMoveAssign() = default;
507+
friend constexpr bool operator==(const NonTrivialMoveAssign& x, const NonTrivialMoveAssign& y) { return x.i == y.i; }
508+
};
509+
510+
TEST_CONSTEXPR_CXX20 bool test_constexpr_move_assignment_non_trivial() {
511+
using V = std::variant<long, void*, NonTrivialMoveAssign>;
512+
static_assert(!std::is_trivially_copyable<V>::value);
513+
static_assert(!std::is_trivially_move_assignable<V>::value);
514+
test_constexpr_assign_imp<0>(V(42l), 101l);
515+
test_constexpr_assign_imp<0>(V(nullptr), 101l);
516+
test_constexpr_assign_imp<1>(V(42l), nullptr);
517+
test_constexpr_assign_imp<2>(V(42l), NonTrivialMoveAssign(5));
518+
test_constexpr_assign_imp<2>(V(NonTrivialMoveAssign(3)), NonTrivialMoveAssign(5));
519+
520+
return true;
490521
}
491522

492523
int main(int, char**) {
@@ -498,11 +529,15 @@ int main(int, char**) {
498529
test_move_assignment_different_index();
499530
test_move_assignment_sfinae();
500531
test_move_assignment_noexcept();
501-
test_constexpr_move_assignment();
502532

533+
test_constexpr_move_assignment_trivial();
534+
test_constexpr_move_assignment_non_trivial();
535+
536+
static_assert(test_constexpr_move_assignment_trivial());
503537
#if TEST_STD_VER >= 20
504538
static_assert(test_move_assignment_same_index());
505539
static_assert(test_move_assignment_different_index());
540+
static_assert(test_constexpr_move_assignment_non_trivial());
506541
#endif
507542
return 0;
508543
}

libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -223,61 +223,64 @@ void test_copy_ctor_valueless_by_exception() {
223223
}
224224

225225
template <std::size_t Idx, class T>
226-
constexpr bool test_constexpr_copy_ctor_imp(const T& v) {
226+
constexpr void test_constexpr_copy_ctor_imp(const T& v) {
227227
auto v2 = v;
228-
return v2.index() == v.index() && v2.index() == Idx && std::get<Idx>(v2) == std::get<Idx>(v);
228+
assert(v2.index() == v.index());
229+
assert(v2.index() == Idx);
230+
assert(std::get<Idx>(v2) == std::get<Idx>(v));
229231
}
230-
#if TEST_STD_VER >= 20
232+
233+
constexpr bool test_constexpr_copy_ctor_trivial() {
234+
// Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
235+
using V = std::variant<long, void*, const int>;
236+
#ifdef TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
237+
static_assert(std::is_trivially_destructible<V>::value, "");
238+
static_assert(std::is_trivially_copy_constructible<V>::value, "");
239+
static_assert(std::is_trivially_move_constructible<V>::value, "");
240+
static_assert(!std::is_copy_assignable<V>::value, "");
241+
static_assert(!std::is_move_assignable<V>::value, "");
242+
#else // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
243+
static_assert(std::is_trivially_copyable<V>::value, "");
244+
#endif // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
245+
static_assert(std::is_trivially_copy_constructible<V>::value, "");
246+
test_constexpr_copy_ctor_imp<0>(V(42l));
247+
test_constexpr_copy_ctor_imp<1>(V(nullptr));
248+
test_constexpr_copy_ctor_imp<2>(V(101));
249+
250+
return true;
251+
}
252+
231253
struct NonTrivialCopyCtor {
232254
int i = 0;
233255
constexpr NonTrivialCopyCtor(int ii) : i(ii) {}
234256
constexpr NonTrivialCopyCtor(const NonTrivialCopyCtor& other) : i(other.i) {}
235-
constexpr NonTrivialCopyCtor(NonTrivialCopyCtor&& other) = default;
236-
constexpr ~NonTrivialCopyCtor() = default;
237-
friend constexpr bool operator==(const NonTrivialCopyCtor&, const NonTrivialCopyCtor&) = default;
257+
constexpr NonTrivialCopyCtor(NonTrivialCopyCtor&& other) = default;
258+
TEST_CONSTEXPR_CXX20 ~NonTrivialCopyCtor() = default;
259+
friend constexpr bool operator==(const NonTrivialCopyCtor& x, const NonTrivialCopyCtor& y) { return x.i == y.i; }
238260
};
239-
#endif
240261

241-
void test_constexpr_copy_ctor() {
242-
{
243-
// Test is_trivially_copy_constructible
244-
// Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
245-
using V = std::variant<long, void*, const int>;
246-
#ifdef TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
247-
static_assert(std::is_trivially_destructible<V>::value, "");
248-
static_assert(std::is_trivially_copy_constructible<V>::value, "");
249-
static_assert(std::is_trivially_move_constructible<V>::value, "");
250-
static_assert(!std::is_copy_assignable<V>::value, "");
251-
static_assert(!std::is_move_assignable<V>::value, "");
252-
#else // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
253-
static_assert(std::is_trivially_copyable<V>::value, "");
254-
#endif // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
255-
static_assert(std::is_trivially_copy_constructible<V>::value, "");
256-
static_assert(test_constexpr_copy_ctor_imp<0>(V(42l)), "");
257-
static_assert(test_constexpr_copy_ctor_imp<1>(V(nullptr)), "");
258-
static_assert(test_constexpr_copy_ctor_imp<2>(V(101)), "");
259-
}
262+
TEST_CONSTEXPR_CXX20 bool test_constexpr_copy_ctor_non_trivial() {
263+
// Test !is_trivially_move_constructible
264+
using V = std::variant<long, NonTrivialCopyCtor, void*>;
265+
static_assert(!std::is_trivially_copy_constructible<V>::value, "");
266+
test_constexpr_copy_ctor_imp<0>(V(42l));
267+
test_constexpr_copy_ctor_imp<1>(V(NonTrivialCopyCtor(5)));
268+
test_constexpr_copy_ctor_imp<2>(V(nullptr));
260269

261-
#if TEST_STD_VER >= 20
262-
{
263-
// Test !is_trivially_move_constructible
264-
using V = std::variant<long, NonTrivialCopyCtor, void*>;
265-
static_assert(!std::is_trivially_copy_constructible<V>::value, "");
266-
static_assert(test_constexpr_copy_ctor_imp<0>(V(42l)), "");
267-
static_assert(test_constexpr_copy_ctor_imp<1>(V(NonTrivialCopyCtor(5))), "");
268-
static_assert(test_constexpr_copy_ctor_imp<2>(V(nullptr)), "");
269-
}
270-
#endif
270+
return true;
271271
}
272272

273273
int main(int, char**) {
274274
test_copy_ctor_basic();
275275
test_copy_ctor_valueless_by_exception();
276276
test_copy_ctor_sfinae();
277-
test_constexpr_copy_ctor();
277+
test_constexpr_copy_ctor_trivial();
278+
test_constexpr_copy_ctor_non_trivial();
278279

280+
static_assert(test_constexpr_copy_ctor_trivial());
279281
#if TEST_STD_VER >= 20
280282
static_assert(test_copy_ctor_basic());
283+
static_assert(test_constexpr_copy_ctor_non_trivial());
281284
#endif
282285
return 0;
283286
}

libcxx/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -295,64 +295,65 @@ void test_move_ctor_valueless_by_exception() {
295295
}
296296

297297
template <std::size_t Idx, class T>
298-
constexpr bool test_constexpr_ctor_imp(const T& v) {
298+
constexpr void test_constexpr_ctor_imp(const T& v) {
299299
auto copy = v;
300300
auto v2 = std::move(copy);
301-
return v2.index() == v.index() && v2.index() == Idx && std::get<Idx>(v2) == std::get<Idx>(v);
301+
assert(v2.index() == v.index());
302+
assert(v2.index() == Idx);
303+
assert(std::get<Idx>(v2) == std::get<Idx>(v));
304+
}
305+
306+
constexpr bool test_constexpr_move_ctor_trivial() {
307+
// Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
308+
using V = std::variant<long, void*, const int>;
309+
#ifdef TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
310+
static_assert(std::is_trivially_destructible<V>::value, "");
311+
static_assert(std::is_trivially_copy_constructible<V>::value, "");
312+
static_assert(std::is_trivially_move_constructible<V>::value, "");
313+
static_assert(!std::is_copy_assignable<V>::value, "");
314+
static_assert(!std::is_move_assignable<V>::value, "");
315+
#else // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
316+
static_assert(std::is_trivially_copyable<V>::value, "");
317+
#endif // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
318+
static_assert(std::is_trivially_move_constructible<V>::value, "");
319+
test_constexpr_ctor_imp<0>(V(42l));
320+
test_constexpr_ctor_imp<1>(V(nullptr));
321+
test_constexpr_ctor_imp<2>(V(101));
322+
323+
return true;
302324
}
303325

304-
#if TEST_STD_VER >= 20
305326
struct NonTrivialMoveCtor {
306327
int i = 0;
307328
constexpr NonTrivialMoveCtor(int ii) : i(ii) {}
308329
constexpr NonTrivialMoveCtor(const NonTrivialMoveCtor& other) = default;
309330
constexpr NonTrivialMoveCtor(NonTrivialMoveCtor&& other) : i(other.i) {}
310-
constexpr ~NonTrivialMoveCtor() = default;
311-
friend constexpr bool operator==(const NonTrivialMoveCtor&, const NonTrivialMoveCtor&) = default;
331+
TEST_CONSTEXPR_CXX20 ~NonTrivialMoveCtor() = default;
332+
friend constexpr bool operator==(const NonTrivialMoveCtor& x, const NonTrivialMoveCtor& y) { return x.i == y.i; }
312333
};
313-
#endif
314334

315-
void test_constexpr_move_ctor() {
316-
{
317-
// Test is_trivially_move_constructible
318-
// Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
319-
using V = std::variant<long, void*, const int>;
320-
#ifdef TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
321-
static_assert(std::is_trivially_destructible<V>::value, "");
322-
static_assert(std::is_trivially_copy_constructible<V>::value, "");
323-
static_assert(std::is_trivially_move_constructible<V>::value, "");
324-
static_assert(!std::is_copy_assignable<V>::value, "");
325-
static_assert(!std::is_move_assignable<V>::value, "");
326-
#else // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
327-
static_assert(std::is_trivially_copyable<V>::value, "");
328-
#endif // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
329-
static_assert(std::is_trivially_move_constructible<V>::value, "");
330-
static_assert(test_constexpr_ctor_imp<0>(V(42l)), "");
331-
static_assert(test_constexpr_ctor_imp<1>(V(nullptr)), "");
332-
static_assert(test_constexpr_ctor_imp<2>(V(101)), "");
333-
}
335+
TEST_CONSTEXPR_CXX20 bool test_constexpr_move_ctor_non_trivial() {
336+
using V = std::variant<long, NonTrivialMoveCtor, void*>;
337+
static_assert(!std::is_trivially_move_constructible<V>::value, "");
338+
test_constexpr_ctor_imp<0>(V(42l));
339+
test_constexpr_ctor_imp<1>(V(NonTrivialMoveCtor(5)));
340+
test_constexpr_ctor_imp<2>(V(nullptr));
334341

335-
#if TEST_STD_VER >= 20
336-
{
337-
// Test !is_trivially_move_constructible
338-
using V = std::variant<long, NonTrivialMoveCtor, void*>;
339-
static_assert(!std::is_trivially_move_constructible<V>::value, "");
340-
static_assert(test_constexpr_ctor_imp<0>(V(42l)), "");
341-
static_assert(test_constexpr_ctor_imp<1>(V(NonTrivialMoveCtor(5))), "");
342-
static_assert(test_constexpr_ctor_imp<2>(V(nullptr)), "");
343-
}
344-
#endif
342+
return true;
345343
}
346344

347345
int main(int, char**) {
348346
test_move_ctor_basic();
349347
test_move_ctor_valueless_by_exception();
350348
test_move_noexcept();
351349
test_move_ctor_sfinae();
352-
test_constexpr_move_ctor();
350+
test_constexpr_move_ctor_trivial();
351+
test_constexpr_move_ctor_non_trivial();
353352

353+
static_assert(test_constexpr_move_ctor_trivial());
354354
#if TEST_STD_VER >= 20
355355
static_assert(test_move_ctor_basic());
356+
static_assert(test_constexpr_move_ctor_non_trivial());
356357
#endif
357358

358359
return 0;

0 commit comments

Comments
 (0)