1a9e65961SEric Fiselier //===----------------------------------------------------------------------===//
2a9e65961SEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9e65961SEric Fiselier //
7a9e65961SEric Fiselier //===----------------------------------------------------------------------===//
8a9e65961SEric Fiselier 
931cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
10a9e65961SEric Fiselier // <optional>
11a9e65961SEric Fiselier 
12a9e65961SEric Fiselier // template <class U>
13a9e65961SEric Fiselier //   optional(optional<U>&& rhs);
14a9e65961SEric Fiselier 
15*52915d78SNikolas Klauser #include <cassert>
16*52915d78SNikolas Klauser #include <memory>
17a9e65961SEric Fiselier #include <optional>
18a9e65961SEric Fiselier #include <type_traits>
19*52915d78SNikolas Klauser #include <utility>
20a9e65961SEric Fiselier 
21a9e65961SEric Fiselier #include "test_macros.h"
22a9e65961SEric Fiselier 
23a9e65961SEric Fiselier using std::optional;
24a9e65961SEric Fiselier 
25a9e65961SEric Fiselier template <class T, class U>
2654644993SChristopher Di Bella TEST_CONSTEXPR_CXX20 void
test(optional<U> && rhs,bool is_going_to_throw=false)27a9e65961SEric Fiselier test(optional<U>&& rhs, bool is_going_to_throw = false)
28a9e65961SEric Fiselier {
29a9e65961SEric Fiselier     bool rhs_engaged = static_cast<bool>(rhs);
30a9e65961SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
31a9e65961SEric Fiselier     try
32a9e65961SEric Fiselier     {
33a9e65961SEric Fiselier         optional<T> lhs = std::move(rhs);
34a9e65961SEric Fiselier         assert(is_going_to_throw == false);
35a9e65961SEric Fiselier         assert(static_cast<bool>(lhs) == rhs_engaged);
36a9e65961SEric Fiselier     }
37a9e65961SEric Fiselier     catch (int i)
38a9e65961SEric Fiselier     {
39a9e65961SEric Fiselier         assert(i == 6);
40a9e65961SEric Fiselier     }
41a9e65961SEric Fiselier #else
42a9e65961SEric Fiselier     if (is_going_to_throw) return;
43a9e65961SEric Fiselier     optional<T> lhs = std::move(rhs);
44a9e65961SEric Fiselier     assert(static_cast<bool>(lhs) == rhs_engaged);
45a9e65961SEric Fiselier #endif
46a9e65961SEric Fiselier }
47a9e65961SEric Fiselier 
48a9e65961SEric Fiselier class X
49a9e65961SEric Fiselier {
50a9e65961SEric Fiselier     int i_;
51a9e65961SEric Fiselier public:
X(int i)5254644993SChristopher Di Bella     TEST_CONSTEXPR_CXX20 X(int i) : i_(i) {}
X(X && x)5354644993SChristopher Di Bella     TEST_CONSTEXPR_CXX20 X(X&& x) : i_(std::exchange(x.i_, 0)) {}
~X()5454644993SChristopher Di Bella     TEST_CONSTEXPR_CXX20 ~X() {i_ = 0;}
operator ==(const X & x,const X & y)5554644993SChristopher Di Bella     friend constexpr bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
56a9e65961SEric Fiselier };
57a9e65961SEric Fiselier 
58a9e65961SEric Fiselier struct Z
59a9e65961SEric Fiselier {
ZZ60a9e65961SEric Fiselier     Z(int) { TEST_THROW(6); }
61a9e65961SEric Fiselier };
62a9e65961SEric Fiselier 
6354644993SChristopher Di Bella template<class T, class U>
test_all()6454644993SChristopher Di Bella TEST_CONSTEXPR_CXX20 bool test_all()
6554644993SChristopher Di Bella {
6654644993SChristopher Di Bella     {
6754644993SChristopher Di Bella         optional<T> rhs;
6854644993SChristopher Di Bella         test<U>(std::move(rhs));
6954644993SChristopher Di Bella     }
7054644993SChristopher Di Bella     {
7154644993SChristopher Di Bella         optional<T> rhs(short{3});
7254644993SChristopher Di Bella         test<U>(std::move(rhs));
7354644993SChristopher Di Bella     }
7454644993SChristopher Di Bella     return true;
7554644993SChristopher Di Bella }
7654644993SChristopher Di Bella 
main(int,char **)772df59c50SJF Bastien int main(int, char**)
78a9e65961SEric Fiselier {
7954644993SChristopher Di Bella     test_all<short, int>();
8054644993SChristopher Di Bella     test_all<int, X>();
8154644993SChristopher Di Bella #if TEST_STD_VER > 17
8254644993SChristopher Di Bella     static_assert(test_all<short, int>());
8354644993SChristopher Di Bella     static_assert(test_all<int, X>());
8454644993SChristopher Di Bella #endif
85a9e65961SEric Fiselier     {
86a9e65961SEric Fiselier         optional<int> rhs;
87a9e65961SEric Fiselier         test<Z>(std::move(rhs));
88a9e65961SEric Fiselier     }
89a9e65961SEric Fiselier     {
90a9e65961SEric Fiselier         optional<int> rhs(3);
91a9e65961SEric Fiselier         test<Z>(std::move(rhs), true);
92a9e65961SEric Fiselier     }
93a9e65961SEric Fiselier 
94a9e65961SEric Fiselier     static_assert(!(std::is_constructible<optional<X>, optional<Z>>::value), "");
952df59c50SJF Bastien 
962df59c50SJF Bastien   return 0;
97a9e65961SEric Fiselier }
98