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 // <optional> 13 14 // template <class U> 15 // constexpr EXPLICIT optional(U&& u); 16 17 #include <optional> 18 #include <type_traits> 19 #include <cassert> 20 21 #include "test_macros.h" 22 #include "archetypes.hpp" 23 #include "test_convertible.hpp" 24 25 26 using std::optional; 27 28 struct ImplicitThrow 29 { 30 constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);} 31 }; 32 33 struct ExplicitThrow 34 { 35 constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);} 36 }; 37 38 39 template <class To, class From> 40 constexpr bool implicit_conversion(optional<To>&& opt, const From& v) 41 { 42 using O = optional<To>; 43 static_assert(test_convertible<O, From>(), ""); 44 static_assert(!test_convertible<O, void*>(), ""); 45 static_assert(!test_convertible<O, From, int>(), ""); 46 return opt && *opt == static_cast<To>(v); 47 } 48 49 template <class To, class Input, class Expect> 50 constexpr bool explicit_conversion(Input&& in, const Expect& v) 51 { 52 using O = optional<To>; 53 static_assert(std::is_constructible<O, Input>::value, ""); 54 static_assert(!std::is_convertible<Input, O>::value, ""); 55 static_assert(!std::is_constructible<O, void*>::value, ""); 56 static_assert(!std::is_constructible<O, Input, int>::value, ""); 57 optional<To> opt(std::forward<Input>(in)); 58 return opt && *opt == static_cast<To>(v); 59 } 60 61 void test_implicit() 62 { 63 { 64 using T = long long; 65 static_assert(implicit_conversion<long long>(42, 42), ""); 66 } 67 { 68 using T = long double; 69 static_assert(implicit_conversion<long double>(3.14, 3.14), ""); 70 } 71 { 72 int x = 42; 73 optional<void* const> o(&x); 74 assert(*o == &x); 75 } 76 { 77 using T = TrivialTestTypes::TestType; 78 static_assert(implicit_conversion<T>(42, 42), ""); 79 } 80 { 81 using T = TestTypes::TestType; 82 assert(implicit_conversion<T>(3, T(3))); 83 } 84 #ifndef TEST_HAS_NO_EXCEPTIONS 85 { 86 try { 87 using T = ImplicitThrow; 88 optional<T> t = 42; 89 assert(false); 90 ((void)t); 91 } catch (int) { 92 } 93 } 94 #endif 95 } 96 97 void test_explicit() { 98 { 99 using T = ExplicitTrivialTestTypes::TestType; 100 using O = optional<T>; 101 static_assert(explicit_conversion<T>(42, 42), ""); 102 } 103 { 104 using T = ExplicitConstexprTestTypes::TestType; 105 using O = optional<T>; 106 static_assert(explicit_conversion<T>(42, 42), ""); 107 static_assert(!std::is_convertible<int, T>::value, ""); 108 } 109 { 110 using T = ExplicitTestTypes::TestType; 111 using O = optional<T>; 112 T::reset(); 113 { 114 assert(explicit_conversion<T>(42, 42)); 115 assert(T::alive == 0); 116 } 117 T::reset(); 118 { 119 optional<T> t(42); 120 assert(T::alive == 1); 121 assert(T::value_constructed == 1); 122 assert(T::move_constructed == 0); 123 assert(T::copy_constructed == 0); 124 assert(t.value().value == 42); 125 } 126 assert(T::alive == 0); 127 } 128 #ifndef TEST_HAS_NO_EXCEPTIONS 129 { 130 try { 131 using T = ExplicitThrow; 132 optional<T> t(42); 133 assert(false); 134 } catch (int) { 135 } 136 } 137 #endif 138 } 139 140 int main() { 141 test_implicit(); 142 test_explicit(); 143 } 144