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> 25 void 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 36 void 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> 60 void 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 70 void 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 135 int main() 136 { 137 test<int>(); 138 test<int>(3); 139 { 140 using T = TestTypes::TestType; 141 T::reset(); 142 optional<T> rhs; 143 assert(T::alive == 0); 144 const optional<T> lhs(std::move(rhs)); 145 assert(lhs.has_value() == false); 146 assert(rhs.has_value() == false); 147 assert(T::alive == 0); 148 } 149 TestTypes::TestType::reset(); 150 { 151 using T = TestTypes::TestType; 152 T::reset(); 153 optional<T> rhs(42); 154 assert(T::alive == 1); 155 assert(T::value_constructed == 1); 156 assert(T::move_constructed == 0); 157 const optional<T> lhs(std::move(rhs)); 158 assert(lhs.has_value()); 159 assert(rhs.has_value()); 160 assert(lhs.value().value == 42); 161 assert(rhs.value().value == -1); 162 assert(T::move_constructed == 1); 163 assert(T::alive == 2); 164 } 165 TestTypes::TestType::reset(); 166 { 167 using namespace ConstexprTestTypes; 168 test<TestType>(); 169 test<TestType>(42); 170 } 171 { 172 using namespace TrivialTestTypes; 173 test<TestType>(); 174 test<TestType>(42); 175 } 176 { 177 test_throwing_ctor(); 178 } 179 { 180 struct ThrowsMove { 181 ThrowsMove() noexcept(false) {} 182 ThrowsMove(ThrowsMove const&) noexcept(false) {} 183 ThrowsMove(ThrowsMove &&) noexcept(false) {} 184 }; 185 static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, ""); 186 struct NoThrowMove { 187 NoThrowMove() noexcept(false) {} 188 NoThrowMove(NoThrowMove const&) noexcept(false) {} 189 NoThrowMove(NoThrowMove &&) noexcept(true) {} 190 }; 191 static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, ""); 192 } 193 { 194 test_reference_extension(); 195 } 196 } 197