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