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 using T = TrivialTestTypes::TestType; 73 static_assert(implicit_conversion<T>(42, 42), ""); 74 } 75 { 76 using T = TestTypes::TestType; 77 assert(implicit_conversion<T>(3, T(3))); 78 } 79 #ifndef TEST_HAS_NO_EXCEPTIONS 80 { 81 try { 82 using T = ImplicitThrow; 83 optional<T> t = 42; 84 assert(false); 85 } catch (int) { 86 } 87 } 88 #endif 89 } 90 91 void test_explicit() { 92 { 93 using T = ExplicitTrivialTestTypes::TestType; 94 using O = optional<T>; 95 static_assert(explicit_conversion<T>(42, 42), ""); 96 } 97 { 98 using T = ExplicitConstexprTestTypes::TestType; 99 using O = optional<T>; 100 static_assert(explicit_conversion<T>(42, 42), ""); 101 static_assert(!std::is_convertible<int, T>::value, ""); 102 } 103 { 104 using T = ExplicitTestTypes::TestType; 105 using O = optional<T>; 106 T::reset(); 107 { 108 assert(explicit_conversion<T>(42, 42)); 109 assert(T::alive == 0); 110 } 111 T::reset(); 112 { 113 optional<T> t(42); 114 assert(T::alive == 1); 115 assert(T::value_constructed == 1); 116 assert(T::move_constructed == 0); 117 assert(T::copy_constructed == 0); 118 assert(t.value().value == 42); 119 } 120 assert(T::alive == 0); 121 } 122 #ifndef TEST_HAS_NO_EXCEPTIONS 123 { 124 try { 125 using T = ExplicitThrow; 126 optional<T> t(42); 127 assert(false); 128 } catch (int) { 129 } 130 } 131 #endif 132 } 133 134 int main() { 135 test_implicit(); 136 test_explicit(); 137 } 138