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 struct ImplicitAny { 39 template <class U> 40 constexpr ImplicitAny(U&&) {} 41 }; 42 43 44 template <class To, class From> 45 constexpr bool implicit_conversion(optional<To>&& opt, const From& v) 46 { 47 using O = optional<To>; 48 static_assert(test_convertible<O, From>(), ""); 49 static_assert(!test_convertible<O, void*>(), ""); 50 static_assert(!test_convertible<O, From, int>(), ""); 51 return opt && *opt == static_cast<To>(v); 52 } 53 54 template <class To, class Input, class Expect> 55 constexpr bool explicit_conversion(Input&& in, const Expect& v) 56 { 57 using O = optional<To>; 58 static_assert(std::is_constructible<O, Input>::value, ""); 59 static_assert(!std::is_convertible<Input, O>::value, ""); 60 static_assert(!std::is_constructible<O, void*>::value, ""); 61 static_assert(!std::is_constructible<O, Input, int>::value, ""); 62 optional<To> opt(std::forward<Input>(in)); 63 return opt && *opt == static_cast<To>(v); 64 } 65 66 void test_implicit() 67 { 68 { 69 static_assert(implicit_conversion<long long>(42, 42), ""); 70 } 71 { 72 static_assert(implicit_conversion<long double>(3.14, 3.14), ""); 73 } 74 { 75 int x = 42; 76 optional<void* const> o(&x); 77 assert(*o == &x); 78 } 79 { 80 using T = TrivialTestTypes::TestType; 81 static_assert(implicit_conversion<T>(42, 42), ""); 82 } 83 { 84 using T = TestTypes::TestType; 85 assert(implicit_conversion<T>(3, T(3))); 86 } 87 { 88 using O = optional<ImplicitAny>; 89 static_assert(!test_convertible<O, std::in_place_t>(), ""); 90 static_assert(!test_convertible<O, std::in_place_t&>(), ""); 91 static_assert(!test_convertible<O, const std::in_place_t&>(), ""); 92 static_assert(!test_convertible<O, std::in_place_t&&>(), ""); 93 static_assert(!test_convertible<O, const std::in_place_t&&>(), ""); 94 95 } 96 #ifndef TEST_HAS_NO_EXCEPTIONS 97 { 98 try { 99 using T = ImplicitThrow; 100 optional<T> t = 42; 101 assert(false); 102 ((void)t); 103 } catch (int) { 104 } 105 } 106 #endif 107 } 108 109 void test_explicit() { 110 { 111 using T = ExplicitTrivialTestTypes::TestType; 112 static_assert(explicit_conversion<T>(42, 42), ""); 113 } 114 { 115 using T = ExplicitConstexprTestTypes::TestType; 116 static_assert(explicit_conversion<T>(42, 42), ""); 117 static_assert(!std::is_convertible<int, T>::value, ""); 118 } 119 { 120 using T = ExplicitTestTypes::TestType; 121 T::reset(); 122 { 123 assert(explicit_conversion<T>(42, 42)); 124 assert(T::alive == 0); 125 } 126 T::reset(); 127 { 128 optional<T> t(42); 129 assert(T::alive == 1); 130 assert(T::value_constructed == 1); 131 assert(T::move_constructed == 0); 132 assert(T::copy_constructed == 0); 133 assert(t.value().value == 42); 134 } 135 assert(T::alive == 0); 136 } 137 #ifndef TEST_HAS_NO_EXCEPTIONS 138 { 139 try { 140 using T = ExplicitThrow; 141 optional<T> t(42); 142 assert(false); 143 } catch (int) { 144 } 145 } 146 #endif 147 } 148 149 int main() { 150 test_implicit(); 151 test_explicit(); 152 } 153