move.pass.cpp (6208B)
1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++98, c++03, c++11, c++14 11 12 // XFAIL: availability=macosx10.13 13 // XFAIL: availability=macosx10.12 14 // XFAIL: availability=macosx10.11 15 // XFAIL: availability=macosx10.10 16 // XFAIL: availability=macosx10.9 17 // XFAIL: availability=macosx10.8 18 // XFAIL: availability=macosx10.7 19 20 // <optional> 21 22 // constexpr optional(optional<T>&& rhs); 23 24 #include <optional> 25 #include <type_traits> 26 #include <cassert> 27 28 #include "test_macros.h" 29 #include "archetypes.hpp" 30 31 using std::optional; 32 33 template <class T, class ...InitArgs> 34 void test(InitArgs&&... args) 35 { 36 const optional<T> orig(std::forward<InitArgs>(args)...); 37 optional<T> rhs(orig); 38 bool rhs_engaged = static_cast<bool>(rhs); 39 optional<T> lhs = std::move(rhs); 40 assert(static_cast<bool>(lhs) == rhs_engaged); 41 if (rhs_engaged) 42 assert(*lhs == *orig); 43 } 44 45 template <class T, class ...InitArgs> 46 constexpr bool constexpr_test(InitArgs&&... args) 47 { 48 static_assert( std::is_trivially_copy_constructible_v<T>, ""); // requirement 49 const optional<T> orig(std::forward<InitArgs>(args)...); 50 optional<T> rhs(orig); 51 optional<T> lhs = std::move(rhs); 52 return (lhs.has_value() == orig.has_value()) && 53 (lhs.has_value() ? *lhs == *orig : true); 54 } 55 56 void test_throwing_ctor() { 57 #ifndef TEST_HAS_NO_EXCEPTIONS 58 struct Z { 59 Z() : count(0) {} 60 Z(Z&& o) : count(o.count + 1) 61 { if (count == 2) throw 6; } 62 int count; 63 }; 64 Z z; 65 optional<Z> rhs(std::move(z)); 66 try 67 { 68 optional<Z> lhs(std::move(rhs)); 69 assert(false); 70 } 71 catch (int i) 72 { 73 assert(i == 6); 74 } 75 #endif 76 } 77 78 79 template <class T, class ...InitArgs> 80 void test_ref(InitArgs&&... args) 81 { 82 optional<T> rhs(std::forward<InitArgs>(args)...); 83 bool rhs_engaged = static_cast<bool>(rhs); 84 optional<T> lhs = std::move(rhs); 85 assert(static_cast<bool>(lhs) == rhs_engaged); 86 if (rhs_engaged) 87 assert(&(*lhs) == &(*rhs)); 88 } 89 90 void test_reference_extension() 91 { 92 #if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. 93 using T = TestTypes::TestType; 94 T::reset(); 95 { 96 T t; 97 T::reset_constructors(); 98 test_ref<T&>(); 99 test_ref<T&>(t); 100 assert(T::alive == 1); 101 assert(T::constructed == 0); 102 assert(T::assigned == 0); 103 assert(T::destroyed == 0); 104 } 105 assert(T::destroyed == 1); 106 assert(T::alive == 0); 107 { 108 T t; 109 const T& ct = t; 110 T::reset_constructors(); 111 test_ref<T const&>(); 112 test_ref<T const&>(t); 113 test_ref<T const&>(ct); 114 assert(T::alive == 1); 115 assert(T::constructed == 0); 116 assert(T::assigned == 0); 117 assert(T::destroyed == 0); 118 } 119 assert(T::alive == 0); 120 assert(T::destroyed == 1); 121 { 122 T t; 123 T::reset_constructors(); 124 test_ref<T&&>(); 125 test_ref<T&&>(std::move(t)); 126 assert(T::alive == 1); 127 assert(T::constructed == 0); 128 assert(T::assigned == 0); 129 assert(T::destroyed == 0); 130 } 131 assert(T::alive == 0); 132 assert(T::destroyed == 1); 133 { 134 T t; 135 const T& ct = t; 136 T::reset_constructors(); 137 test_ref<T const&&>(); 138 test_ref<T const&&>(std::move(t)); 139 test_ref<T const&&>(std::move(ct)); 140 assert(T::alive == 1); 141 assert(T::constructed == 0); 142 assert(T::assigned == 0); 143 assert(T::destroyed == 0); 144 } 145 assert(T::alive == 0); 146 assert(T::destroyed == 1); 147 { 148 static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, ""); 149 static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, ""); 150 } 151 #endif 152 } 153 154 155 int main() 156 { 157 test<int>(); 158 test<int>(3); 159 static_assert(constexpr_test<int>(), "" ); 160 static_assert(constexpr_test<int>(3), "" ); 161 162 { 163 optional<const int> o(42); 164 optional<const int> o2(std::move(o)); 165 assert(*o2 == 42); 166 } 167 { 168 using T = TestTypes::TestType; 169 T::reset(); 170 optional<T> rhs; 171 assert(T::alive == 0); 172 const optional<T> lhs(std::move(rhs)); 173 assert(lhs.has_value() == false); 174 assert(rhs.has_value() == false); 175 assert(T::alive == 0); 176 } 177 TestTypes::TestType::reset(); 178 { 179 using T = TestTypes::TestType; 180 T::reset(); 181 optional<T> rhs(42); 182 assert(T::alive == 1); 183 assert(T::value_constructed == 1); 184 assert(T::move_constructed == 0); 185 const optional<T> lhs(std::move(rhs)); 186 assert(lhs.has_value()); 187 assert(rhs.has_value()); 188 assert(lhs.value().value == 42); 189 assert(rhs.value().value == -1); 190 assert(T::move_constructed == 1); 191 assert(T::alive == 2); 192 } 193 TestTypes::TestType::reset(); 194 { 195 using namespace ConstexprTestTypes; 196 test<TestType>(); 197 test<TestType>(42); 198 } 199 { 200 using namespace TrivialTestTypes; 201 test<TestType>(); 202 test<TestType>(42); 203 } 204 { 205 test_throwing_ctor(); 206 } 207 { 208 struct ThrowsMove { 209 ThrowsMove() noexcept(false) {} 210 ThrowsMove(ThrowsMove const&) noexcept(false) {} 211 ThrowsMove(ThrowsMove &&) noexcept(false) {} 212 }; 213 static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, ""); 214 struct NoThrowMove { 215 NoThrowMove() noexcept(false) {} 216 NoThrowMove(NoThrowMove const&) noexcept(false) {} 217 NoThrowMove(NoThrowMove &&) noexcept(true) {} 218 }; 219 static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, ""); 220 } 221 { 222 test_reference_extension(); 223 } 224 { 225 constexpr std::optional<int> o1{4}; 226 constexpr std::optional<int> o2 = std::move(o1); 227 static_assert( *o2 == 4, "" ); 228 } 229 }