1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // UNSUPPORTED: c++03, c++11, c++14 10 11 // XFAIL: dylib-has-no-bad_optional_access && !no-exceptions 12 13 // <optional> 14 15 // template <class U> 16 // constexpr EXPLICIT optional(U&& u); 17 18 #include <optional> 19 #include <type_traits> 20 #include <cassert> 21 22 #include "test_macros.h" 23 #include "archetypes.h" 24 #include "test_convertible.h" 25 26 27 using std::optional; 28 29 struct ImplicitThrow 30 { 31 constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);} 32 }; 33 34 struct ExplicitThrow 35 { 36 constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);} 37 }; 38 39 struct ImplicitAny { 40 template <class U> 41 constexpr ImplicitAny(U&&) {} 42 }; 43 44 45 template <class To, class From> 46 constexpr bool implicit_conversion(optional<To>&& opt, const From& v) 47 { 48 using O = optional<To>; 49 static_assert(test_convertible<O, From>(), ""); 50 static_assert(!test_convertible<O, void*>(), ""); 51 static_assert(!test_convertible<O, From, int>(), ""); 52 return opt && *opt == static_cast<To>(v); 53 } 54 55 template <class To, class Input, class Expect> 56 constexpr bool explicit_conversion(Input&& in, const Expect& v) 57 { 58 using O = optional<To>; 59 static_assert(std::is_constructible<O, Input>::value, ""); 60 static_assert(!std::is_convertible<Input, O>::value, ""); 61 static_assert(!std::is_constructible<O, void*>::value, ""); 62 static_assert(!std::is_constructible<O, Input, int>::value, ""); 63 optional<To> opt(std::forward<Input>(in)); 64 return opt && *opt == static_cast<To>(v); 65 } 66 67 void test_implicit() 68 { 69 { 70 static_assert(implicit_conversion<long long>(42, 42), ""); 71 } 72 { 73 static_assert(implicit_conversion<long double>(3.14, 3.14), ""); 74 } 75 { 76 int x = 42; 77 optional<void* const> o(&x); 78 assert(*o == &x); 79 } 80 { 81 using T = TrivialTestTypes::TestType; 82 static_assert(implicit_conversion<T>(42, 42), ""); 83 } 84 { 85 using T = TestTypes::TestType; 86 assert(implicit_conversion<T>(3, T(3))); 87 } 88 { 89 using O = optional<ImplicitAny>; 90 static_assert(!test_convertible<O, std::in_place_t>(), ""); 91 static_assert(!test_convertible<O, std::in_place_t&>(), ""); 92 static_assert(!test_convertible<O, const std::in_place_t&>(), ""); 93 static_assert(!test_convertible<O, std::in_place_t&&>(), ""); 94 static_assert(!test_convertible<O, const std::in_place_t&&>(), ""); 95 96 } 97 #ifndef TEST_HAS_NO_EXCEPTIONS 98 { 99 try { 100 using T = ImplicitThrow; 101 optional<T> t = 42; 102 assert(false); 103 ((void)t); 104 } catch (int) { 105 } 106 } 107 #endif 108 } 109 110 void test_explicit() { 111 { 112 using T = ExplicitTrivialTestTypes::TestType; 113 static_assert(explicit_conversion<T>(42, 42), ""); 114 } 115 { 116 using T = ExplicitConstexprTestTypes::TestType; 117 static_assert(explicit_conversion<T>(42, 42), ""); 118 static_assert(!std::is_convertible<int, T>::value, ""); 119 } 120 { 121 using T = ExplicitTestTypes::TestType; 122 T::reset(); 123 { 124 assert(explicit_conversion<T>(42, 42)); 125 assert(T::alive == 0); 126 } 127 T::reset(); 128 { 129 optional<T> t(42); 130 assert(T::alive == 1); 131 assert(T::value_constructed == 1); 132 assert(T::move_constructed == 0); 133 assert(T::copy_constructed == 0); 134 assert(t.value().value == 42); 135 } 136 assert(T::alive == 0); 137 } 138 #ifndef TEST_HAS_NO_EXCEPTIONS 139 { 140 try { 141 using T = ExplicitThrow; 142 optional<T> t(42); 143 assert(false); 144 } catch (int) { 145 } 146 } 147 #endif 148 } 149 150 int main(int, char**) { 151 test_implicit(); 152 test_explicit(); 153 154 return 0; 155 } 156