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 // test move
10
11 #include <utility>
12 #include <type_traits>
13 #include <cassert>
14
15 #include "test_macros.h"
16
17 class move_only
18 {
19 move_only(const move_only&);
20 move_only& operator=(const move_only&);
21 public:
move_only(move_only &&)22 move_only(move_only&&) {}
operator =(move_only &&)23 move_only& operator=(move_only&&) {return *this;}
24
move_only()25 move_only() {}
26 };
27
source()28 move_only source() {return move_only();}
csource()29 const move_only csource() {return move_only();}
30
test(move_only)31 void test(move_only) {}
32
33 int x = 42;
34 const int& cx = x;
35
36 template <class QualInt>
get()37 QualInt get() TEST_NOEXCEPT { return static_cast<QualInt>(x); }
38
39
40 int copy_ctor = 0;
41 int move_ctor = 0;
42
43 struct A {
AA44 A() {}
AA45 A(const A&) {++copy_ctor;}
AA46 A(A&&) {++move_ctor;}
47 A& operator=(const A&) = delete;
48 };
49
50 #if TEST_STD_VER > 11
test_constexpr_move()51 constexpr bool test_constexpr_move() {
52 int y = 42;
53 const int cy = y;
54 return std::move(y) == 42
55 && std::move(cy) == 42
56 && std::move(static_cast<int&&>(y)) == 42
57 && std::move(static_cast<int const&&>(y)) == 42;
58 }
59 #endif
main(int,char **)60 int main(int, char**)
61 {
62 { // Test return type and noexcept.
63 static_assert(std::is_same<decltype(std::move(x)), int&&>::value, "");
64 ASSERT_NOEXCEPT(std::move(x));
65 static_assert(std::is_same<decltype(std::move(cx)), const int&&>::value, "");
66 ASSERT_NOEXCEPT(std::move(cx));
67 static_assert(std::is_same<decltype(std::move(42)), int&&>::value, "");
68 ASSERT_NOEXCEPT(std::move(42));
69 static_assert(std::is_same<decltype(std::move(get<const int&&>())), const int&&>::value, "");
70 ASSERT_NOEXCEPT(std::move(get<int const&&>()));
71 }
72 { // test copy and move semantics
73 A a;
74 const A ca = A();
75
76 assert(copy_ctor == 0);
77 assert(move_ctor == 0);
78
79 A a2 = a; (void)a2;
80 assert(copy_ctor == 1);
81 assert(move_ctor == 0);
82
83 A a3 = std::move(a); (void)a3;
84 assert(copy_ctor == 1);
85 assert(move_ctor == 1);
86
87 A a4 = ca; (void)a4;
88 assert(copy_ctor == 2);
89 assert(move_ctor == 1);
90
91 A a5 = std::move(ca); (void)a5;
92 assert(copy_ctor == 3);
93 assert(move_ctor == 1);
94 }
95 { // test on a move only type
96 move_only mo;
97 test(std::move(mo));
98 test(source());
99 }
100 #if TEST_STD_VER > 11
101 {
102 constexpr int y = 42;
103 static_assert(std::move(y) == 42, "");
104 static_assert(test_constexpr_move(), "");
105 }
106 #endif
107 #if TEST_STD_VER == 11 && defined(_LIBCPP_VERSION)
108 // Test that std::forward is constexpr in C++11. This is an extension
109 // provided by both libc++ and libstdc++.
110 {
111 constexpr int y = 42;
112 static_assert(std::move(y) == 42, "");
113 }
114 #endif
115
116 return 0;
117 }
118