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// <optional>
11
12// constexpr optional(const optional<T>& rhs);
13
14#include <optional>
15#include <type_traits>
16#include <cassert>
17
18#include "test_macros.h"
19#include "archetypes.h"
20
21using std::optional;
22
23template <class T, class ...InitArgs>
24void test(InitArgs&&... args)
25{
26 const optional<T> rhs(std::forward<InitArgs>(args)...);
27 bool rhs_engaged = static_cast<bool>(rhs);
28 optional<T> lhs = rhs;
29 assert(static_cast<bool>(lhs) == rhs_engaged);
30 if (rhs_engaged)
31 assert(*lhs == *rhs);
32}
33
34template <class T, class ...InitArgs>
35constexpr bool constexpr_test(InitArgs&&... args)
36{
37 static_assert( std::is_trivially_copy_constructible_v<T>, ""); // requirement
38 const optional<T> rhs(std::forward<InitArgs>(args)...);
39 optional<T> lhs = rhs;
40 return (lhs.has_value() == rhs.has_value()) &&
41 (lhs.has_value() ? *lhs == *rhs : true);
42}
43
44void test_throwing_ctor() {
45#ifndef TEST_HAS_NO_EXCEPTIONS
46 struct Z {
47 Z() : count(0) {}
48 Z(Z const& o) : count(o.count + 1)
49 { if (count == 2) throw 6; }
50 int count;
51 };
52 const Z z;
53 const optional<Z> rhs(z);
54 try
55 {
56 optional<Z> lhs(rhs);
57 assert(false);
58 }
59 catch (int i)
60 {
61 assert(i == 6);
62 }
63#endif
64}
65
66template <class T, class ...InitArgs>
67void test_ref(InitArgs&&... args)
68{
69 const optional<T> rhs(std::forward<InitArgs>(args)...);
70 bool rhs_engaged = static_cast<bool>(rhs);
71 optional<T> lhs = rhs;
72 assert(static_cast<bool>(lhs) == rhs_engaged);
73 if (rhs_engaged)
74 assert(&(*lhs) == &(*rhs));
75}
76
77
78void test_reference_extension()
79{
80#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
81 using T = TestTypes::TestType;
82 T::reset();
83 {
84 T t;
85 T::reset_constructors();
86 test_ref<T&>();
87 test_ref<T&>(t);
88 assert(T::alive == 1);
89 assert(T::constructed == 0);
90 assert(T::assigned == 0);
91 assert(T::destroyed == 0);
92 }
93 assert(T::destroyed == 1);
94 assert(T::alive == 0);
95 {
96 T t;
97 const T& ct = t;
98 T::reset_constructors();
99 test_ref<T const&>();
100 test_ref<T const&>(t);
101 test_ref<T const&>(ct);
102 assert(T::alive == 1);
103 assert(T::constructed == 0);
104 assert(T::assigned == 0);
105 assert(T::destroyed == 0);
106 }
107 assert(T::alive == 0);
108 assert(T::destroyed == 1);
109 {
110 static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
111 static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
112 }
113#endif
114}
115
116int main(int, char**)
117{
118 test<int>();
119 test<int>(args: 3);
120 static_assert(constexpr_test<int>(), "" );
121 static_assert(constexpr_test<int>(args: 3), "" );
122
123 {
124 const optional<const int> o(42);
125 optional<const int> o2(o);
126 assert(*o2 == 42);
127 }
128 {
129 using T = TestTypes::TestType;
130 T::reset();
131 const optional<T> rhs;
132 assert(T::alive == 0);
133 const optional<T> lhs(rhs);
134 assert(lhs.has_value() == false);
135 assert(T::alive == 0);
136 }
137 TestTypes::TestType::reset();
138 {
139 using T = TestTypes::TestType;
140 T::reset();
141 const optional<T> rhs(42);
142 assert(T::alive == 1);
143 assert(T::value_constructed == 1);
144 assert(T::copy_constructed == 0);
145 const optional<T> lhs(rhs);
146 assert(lhs.has_value());
147 assert(T::copy_constructed == 1);
148 assert(T::alive == 2);
149 }
150 TestTypes::TestType::reset();
151 {
152 using namespace ConstexprTestTypes;
153 test<TestType>();
154 test<TestType>(42);
155 }
156 {
157 using namespace TrivialTestTypes;
158 test<TestType>();
159 test<TestType>(42);
160 }
161 {
162 test_throwing_ctor();
163 }
164 {
165 test_reference_extension();
166 }
167 {
168 constexpr std::optional<int> o1{4};
169 constexpr std::optional<int> o2 = o1;
170 static_assert( *o2 == 4, "" );
171 }
172
173 // LWG3836 https://wg21.link/LWG3836
174 // std::optional<bool> conversion constructor optional(const optional<U>&)
175 // should take precedence over optional(U&&) with operator bool
176 {
177 std::optional<bool> o1(false);
178 std::optional<bool> o2(o1);
179 assert(!o2.value());
180 }
181
182 return 0;
183}
184

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