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 // template <class U>
13 //   explicit optional(const optional<U>& rhs);
14 
15 #include <optional>
16 #include <type_traits>
17 #include <cassert>
18 
19 #include "test_macros.h"
20 
21 using std::optional;
22 
23 template <class T, class U>
24 TEST_CONSTEXPR_CXX20 void
test(const optional<U> & rhs,bool is_going_to_throw=false)25 test(const optional<U>& rhs, bool is_going_to_throw = false)
26 {
27     static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value), "");
28     bool rhs_engaged = static_cast<bool>(rhs);
29 #ifndef TEST_HAS_NO_EXCEPTIONS
30     try
31     {
32         optional<T> lhs(rhs);
33         assert(is_going_to_throw == false);
34         assert(static_cast<bool>(lhs) == rhs_engaged);
35         if (rhs_engaged)
36             assert(*lhs == T(*rhs));
37     }
38     catch (int i)
39     {
40         assert(i == 6);
41     }
42 #else
43     if (is_going_to_throw) return;
44     optional<T> lhs(rhs);
45     assert(static_cast<bool>(lhs) == rhs_engaged);
46     if (rhs_engaged)
47         assert(*lhs == T(*rhs));
48 #endif
49 }
50 
51 class X
52 {
53     int i_;
54 public:
X(int i)55     constexpr explicit X(int i) : i_(i) {}
X(const X & x)56     constexpr X(const X& x) : i_(x.i_) {}
~X()57     TEST_CONSTEXPR_CXX20 ~X() {i_ = 0;}
operator ==(const X & x,const X & y)58     friend constexpr bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
59 };
60 
61 class Y
62 {
63     int i_;
64 public:
Y(int i)65     constexpr explicit Y(int i) : i_(i) {}
66 
operator ==(const Y & x,const Y & y)67     friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
68 };
69 
70 int count = 0;
71 
72 class Z
73 {
74     int i_;
75 public:
Z(int i)76     explicit Z(int i) : i_(i) {TEST_THROW(6);}
77 
operator ==(const Z & x,const Z & y)78     friend bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
79 };
80 
81 template<class T, class U>
test_all()82 constexpr bool test_all()
83 {
84   {
85     optional<U> rhs;
86     test<T>(rhs);
87   }
88   {
89     optional<U> rhs(3);
90     test<T>(rhs);
91   }
92   return true;
93 }
94 
95 
main(int,char **)96 int main(int, char**)
97 {
98     test_all<X, int>();
99     test_all<Y, int>();
100 #if TEST_STD_VER > 17
101     static_assert(test_all<X, int>());
102     static_assert(test_all<Y, int>());
103 #endif
104     {
105         typedef Z T;
106         typedef int U;
107         optional<U> rhs;
108         test<T>(rhs);
109     }
110     {
111         typedef Z T;
112         typedef int U;
113         optional<U> rhs(3);
114         test<T>(rhs, true);
115     }
116 
117   return 0;
118 }
119