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
25using std::optional;
26
27struct ImplicitThrow
28{
29 constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);}
30};
31
32struct ExplicitThrow
33{
34 constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);}
35};
36
37struct ImplicitAny {
38 template <class U>
39 constexpr ImplicitAny(U&&) {}
40};
41
42
43template <class To, class From>
44constexpr 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
53template <class To, class Input, class Expect>
54constexpr 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
65void 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
108void 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
148int main(int, char**) {
149 test_implicit();
150 test_explicit();
151
152 return 0;
153}
154

source code of libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp