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