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