xref: /llvm-project/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp (revision ec350ad418a24f70c88758259c774a1e11c06d74)
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