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