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 } catch (int) { 91 } 92 } 93 #endif 94 } 95 96 void test_explicit() { 97 { 98 using T = ExplicitTrivialTestTypes::TestType; 99 using O = optional<T>; 100 static_assert(explicit_conversion<T>(42, 42), ""); 101 } 102 { 103 using T = ExplicitConstexprTestTypes::TestType; 104 using O = optional<T>; 105 static_assert(explicit_conversion<T>(42, 42), ""); 106 static_assert(!std::is_convertible<int, T>::value, ""); 107 } 108 { 109 using T = ExplicitTestTypes::TestType; 110 using O = optional<T>; 111 T::reset(); 112 { 113 assert(explicit_conversion<T>(42, 42)); 114 assert(T::alive == 0); 115 } 116 T::reset(); 117 { 118 optional<T> t(42); 119 assert(T::alive == 1); 120 assert(T::value_constructed == 1); 121 assert(T::move_constructed == 0); 122 assert(T::copy_constructed == 0); 123 assert(t.value().value == 42); 124 } 125 assert(T::alive == 0); 126 } 127 #ifndef TEST_HAS_NO_EXCEPTIONS 128 { 129 try { 130 using T = ExplicitThrow; 131 optional<T> t(42); 132 assert(false); 133 } catch (int) { 134 } 135 } 136 #endif 137 } 138 139 int main() { 140 test_implicit(); 141 test_explicit(); 142 } 143