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 // 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 void test_throwing_ctor() { 45 #ifndef TEST_HAS_NO_EXCEPTIONS 46 struct Z { 47 Z() : count(0) {} 48 Z(Z&& o) : count(o.count + 1) 49 { if (count == 2) throw 6; } 50 int count; 51 }; 52 Z z; 53 optional<Z> rhs(std::move(z)); 54 try 55 { 56 optional<Z> lhs(std::move(rhs)); 57 assert(false); 58 } 59 catch (int i) 60 { 61 assert(i == 6); 62 } 63 #endif 64 } 65 66 67 template <class T, class ...InitArgs> 68 void test_ref(InitArgs&&... args) 69 { 70 optional<T> rhs(std::forward<InitArgs>(args)...); 71 bool rhs_engaged = static_cast<bool>(rhs); 72 optional<T> lhs = std::move(rhs); 73 assert(static_cast<bool>(lhs) == rhs_engaged); 74 if (rhs_engaged) 75 assert(&(*lhs) == &(*rhs)); 76 } 77 78 void test_reference_extension() 79 { 80 #if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. 81 using T = TestTypes::TestType; 82 T::reset(); 83 { 84 T t; 85 T::reset_constructors(); 86 test_ref<T&>(); 87 test_ref<T&>(t); 88 assert(T::alive == 1); 89 assert(T::constructed == 0); 90 assert(T::assigned == 0); 91 assert(T::destroyed == 0); 92 } 93 assert(T::destroyed == 1); 94 assert(T::alive == 0); 95 { 96 T t; 97 const T& ct = t; 98 T::reset_constructors(); 99 test_ref<T const&>(); 100 test_ref<T const&>(t); 101 test_ref<T const&>(ct); 102 assert(T::alive == 1); 103 assert(T::constructed == 0); 104 assert(T::assigned == 0); 105 assert(T::destroyed == 0); 106 } 107 assert(T::alive == 0); 108 assert(T::destroyed == 1); 109 { 110 T t; 111 T::reset_constructors(); 112 test_ref<T&&>(); 113 test_ref<T&&>(std::move(t)); 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 const T& ct = t; 124 T::reset_constructors(); 125 test_ref<T const&&>(); 126 test_ref<T const&&>(std::move(t)); 127 test_ref<T const&&>(std::move(ct)); 128 assert(T::alive == 1); 129 assert(T::constructed == 0); 130 assert(T::assigned == 0); 131 assert(T::destroyed == 0); 132 } 133 assert(T::alive == 0); 134 assert(T::destroyed == 1); 135 { 136 static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, ""); 137 static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, ""); 138 } 139 #endif 140 } 141 142 143 int main() 144 { 145 test<int>(); 146 test<int>(3); 147 { 148 optional<const int> o(42); 149 optional<const int> o2(std::move(o)); 150 assert(*o2 == 42); 151 } 152 { 153 using T = TestTypes::TestType; 154 T::reset(); 155 optional<T> rhs; 156 assert(T::alive == 0); 157 const optional<T> lhs(std::move(rhs)); 158 assert(lhs.has_value() == false); 159 assert(rhs.has_value() == false); 160 assert(T::alive == 0); 161 } 162 TestTypes::TestType::reset(); 163 { 164 using T = TestTypes::TestType; 165 T::reset(); 166 optional<T> rhs(42); 167 assert(T::alive == 1); 168 assert(T::value_constructed == 1); 169 assert(T::move_constructed == 0); 170 const optional<T> lhs(std::move(rhs)); 171 assert(lhs.has_value()); 172 assert(rhs.has_value()); 173 assert(lhs.value().value == 42); 174 assert(rhs.value().value == -1); 175 assert(T::move_constructed == 1); 176 assert(T::alive == 2); 177 } 178 TestTypes::TestType::reset(); 179 { 180 using namespace ConstexprTestTypes; 181 test<TestType>(); 182 test<TestType>(42); 183 } 184 { 185 using namespace TrivialTestTypes; 186 test<TestType>(); 187 test<TestType>(42); 188 } 189 { 190 test_throwing_ctor(); 191 } 192 { 193 struct ThrowsMove { 194 ThrowsMove() noexcept(false) {} 195 ThrowsMove(ThrowsMove const&) noexcept(false) {} 196 ThrowsMove(ThrowsMove &&) noexcept(false) {} 197 }; 198 static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, ""); 199 struct NoThrowMove { 200 NoThrowMove() noexcept(false) {} 201 NoThrowMove(NoThrowMove const&) noexcept(false) {} 202 NoThrowMove(NoThrowMove &&) noexcept(true) {} 203 }; 204 static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, ""); 205 } 206 { 207 test_reference_extension(); 208 } 209 } 210