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