15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier
95a83710eSEric Fiselier // <utility>
105a83710eSEric Fiselier
115a83710eSEric Fiselier // template<class T>
125a83710eSEric Fiselier // requires MoveAssignable<T> && MoveConstructible<T>
135a83710eSEric Fiselier // void
145a83710eSEric Fiselier // swap(T& a, T& b);
155a83710eSEric Fiselier
165a83710eSEric Fiselier #include <cassert>
175a83710eSEric Fiselier #include <memory>
18*6adbc83eSChristopher Di Bella #include <type_traits>
19*6adbc83eSChristopher Di Bella #include <utility>
20f07dd8d0SEric Fiselier
21f07dd8d0SEric Fiselier #include "test_macros.h"
22f07dd8d0SEric Fiselier
23f07dd8d0SEric Fiselier #if TEST_STD_VER >= 11
24f07dd8d0SEric Fiselier struct CopyOnly {
CopyOnlyCopyOnly25f07dd8d0SEric Fiselier CopyOnly() {}
CopyOnlyCopyOnly26f07dd8d0SEric Fiselier CopyOnly(CopyOnly const&) noexcept {}
operator =CopyOnly27f07dd8d0SEric Fiselier CopyOnly& operator=(CopyOnly const&) { return *this; }
28f07dd8d0SEric Fiselier };
29f07dd8d0SEric Fiselier
30f07dd8d0SEric Fiselier struct MoveOnly {
MoveOnlyMoveOnly31f07dd8d0SEric Fiselier MoveOnly() {}
MoveOnlyMoveOnly32f07dd8d0SEric Fiselier MoveOnly(MoveOnly&&) {}
operator =MoveOnly33f07dd8d0SEric Fiselier MoveOnly& operator=(MoveOnly&&) noexcept { return *this; }
34f07dd8d0SEric Fiselier };
35f07dd8d0SEric Fiselier
36f07dd8d0SEric Fiselier struct NoexceptMoveOnly {
NoexceptMoveOnlyNoexceptMoveOnly37f07dd8d0SEric Fiselier NoexceptMoveOnly() {}
NoexceptMoveOnlyNoexceptMoveOnly38f07dd8d0SEric Fiselier NoexceptMoveOnly(NoexceptMoveOnly&&) noexcept {}
operator =NoexceptMoveOnly39f07dd8d0SEric Fiselier NoexceptMoveOnly& operator=(NoexceptMoveOnly&&) noexcept { return *this; }
40f07dd8d0SEric Fiselier };
41f07dd8d0SEric Fiselier
42f07dd8d0SEric Fiselier struct NotMoveConstructible {
operator =NotMoveConstructible43f07dd8d0SEric Fiselier NotMoveConstructible& operator=(NotMoveConstructible&&) { return *this; }
44f07dd8d0SEric Fiselier private:
45f07dd8d0SEric Fiselier NotMoveConstructible(NotMoveConstructible&&);
46f07dd8d0SEric Fiselier };
47f07dd8d0SEric Fiselier
48f07dd8d0SEric Fiselier struct NotMoveAssignable {
49f07dd8d0SEric Fiselier NotMoveAssignable(NotMoveAssignable&&);
50f07dd8d0SEric Fiselier private:
51f07dd8d0SEric Fiselier NotMoveAssignable& operator=(NotMoveAssignable&&);
52f07dd8d0SEric Fiselier };
53f07dd8d0SEric Fiselier
54f07dd8d0SEric Fiselier template <class Tp>
55f07dd8d0SEric Fiselier auto can_swap_test(int) -> decltype(std::swap(std::declval<Tp>(), std::declval<Tp>()));
56f07dd8d0SEric Fiselier
57f07dd8d0SEric Fiselier template <class Tp>
58f07dd8d0SEric Fiselier auto can_swap_test(...) -> std::false_type;
59f07dd8d0SEric Fiselier
60f07dd8d0SEric Fiselier template <class Tp>
can_swap()61f07dd8d0SEric Fiselier constexpr bool can_swap() {
62f07dd8d0SEric Fiselier return std::is_same<decltype(can_swap_test<Tp>(0)), void>::value;
63f07dd8d0SEric Fiselier }
645a83710eSEric Fiselier #endif
655a83710eSEric Fiselier
6628e01871SZoe Carver #if TEST_STD_VER > 17
test_swap_constexpr()6728e01871SZoe Carver constexpr bool test_swap_constexpr()
6828e01871SZoe Carver {
6928e01871SZoe Carver int i = 1;
7028e01871SZoe Carver int j = 2;
7128e01871SZoe Carver std::swap(i, j);
7228e01871SZoe Carver return i == 2 && j == 1;
7328e01871SZoe Carver }
7428e01871SZoe Carver #endif // TEST_STD_VER > 17
7528e01871SZoe Carver
main(int,char **)762df59c50SJF Bastien int main(int, char**)
77f07dd8d0SEric Fiselier {
78f07dd8d0SEric Fiselier
795a83710eSEric Fiselier {
805a83710eSEric Fiselier int i = 1;
815a83710eSEric Fiselier int j = 2;
825a83710eSEric Fiselier std::swap(i, j);
835a83710eSEric Fiselier assert(i == 2);
845a83710eSEric Fiselier assert(j == 1);
855a83710eSEric Fiselier }
86f07dd8d0SEric Fiselier #if TEST_STD_VER >= 11
875a83710eSEric Fiselier {
88f07dd8d0SEric Fiselier
895a83710eSEric Fiselier std::unique_ptr<int> i(new int(1));
905a83710eSEric Fiselier std::unique_ptr<int> j(new int(2));
915a83710eSEric Fiselier std::swap(i, j);
925a83710eSEric Fiselier assert(*i == 2);
935a83710eSEric Fiselier assert(*j == 1);
94f07dd8d0SEric Fiselier
955a83710eSEric Fiselier }
965a83710eSEric Fiselier {
97f07dd8d0SEric Fiselier // test that the swap
98f07dd8d0SEric Fiselier static_assert(can_swap<CopyOnly&>(), "");
99f07dd8d0SEric Fiselier static_assert(can_swap<MoveOnly&>(), "");
100f07dd8d0SEric Fiselier static_assert(can_swap<NoexceptMoveOnly&>(), "");
101f07dd8d0SEric Fiselier
102f07dd8d0SEric Fiselier static_assert(!can_swap<NotMoveConstructible&>(), "");
103f07dd8d0SEric Fiselier static_assert(!can_swap<NotMoveAssignable&>(), "");
104f07dd8d0SEric Fiselier
105f07dd8d0SEric Fiselier CopyOnly c;
106f07dd8d0SEric Fiselier MoveOnly m;
107f07dd8d0SEric Fiselier NoexceptMoveOnly nm;
108f07dd8d0SEric Fiselier static_assert(!noexcept(std::swap(c, c)), "");
109f07dd8d0SEric Fiselier static_assert(!noexcept(std::swap(m, m)), "");
110f07dd8d0SEric Fiselier static_assert(noexcept(std::swap(nm, nm)), "");
111f07dd8d0SEric Fiselier }
1125a83710eSEric Fiselier #endif
1132df59c50SJF Bastien
11428e01871SZoe Carver #if TEST_STD_VER > 17
11528e01871SZoe Carver static_assert(test_swap_constexpr());
11628e01871SZoe Carver #endif // TEST_STD_VER > 17
11728e01871SZoe Carver
1182df59c50SJF Bastien return 0;
1195a83710eSEric Fiselier }
120