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