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 | { |
29 | constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);} |
30 | }; |
31 | |
32 | struct ExplicitThrow |
33 | { |
34 | constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);} |
35 | }; |
36 | |
37 | struct ImplicitAny { |
38 | template <class U> |
39 | constexpr ImplicitAny(U&&) {} |
40 | }; |
41 | |
42 | |
43 | template <class To, class From> |
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> |
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 | |
65 | void test_implicit() |
66 | { |
67 | { |
68 | static_assert(implicit_conversion<long long>(opt: 42, v: 42), "" ); |
69 | } |
70 | { |
71 | static_assert(implicit_conversion<long double>(opt: 3.14, v: 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 | |
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 | |
148 | int main(int, char**) { |
149 | test_implicit(); |
150 | test_explicit(); |
151 | |
152 | return 0; |
153 | } |
154 | |