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