xref: /llvm-project/libcxx/test/std/utilities/expected/expected.expected/observers/value.pass.cpp (revision 6a54dfbfe534276d644d7f9c027f0deeb748dd53)
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, c++17, c++20
10 
11 // constexpr const T& value() const &;
12 // constexpr T& value() &;
13 // constexpr T&& value() &&;
14 // constexpr const T&& value() const &&;
15 
16 #include <cassert>
17 #include <concepts>
18 #include <expected>
19 #include <type_traits>
20 #include <utility>
21 
22 #include "test_macros.h"
23 
24 constexpr bool test() {
25   // non-const &
26   {
27     std::expected<int, int> e(5);
28     decltype(auto) x = e.value();
29     static_assert(std::same_as<decltype(x), int&>);
30     assert(&x == &(*e));
31     assert(x == 5);
32   }
33 
34   // const &
35   {
36     const std::expected<int, int> e(5);
37     decltype(auto) x = e.value();
38     static_assert(std::same_as<decltype(x), const int&>);
39     assert(&x == &(*e));
40     assert(x == 5);
41   }
42 
43   // non-const &&
44   {
45     std::expected<int, int> e(5);
46     decltype(auto) x = std::move(e).value();
47     static_assert(std::same_as<decltype(x), int&&>);
48     assert(&x == &(*e));
49     assert(x == 5);
50   }
51 
52   // const &&
53   {
54     const std::expected<int, int> e(5);
55     decltype(auto) x = std::move(e).value();
56     static_assert(std::same_as<decltype(x), const int&&>);
57     assert(&x == &(*e));
58     assert(x == 5);
59   }
60 
61   return true;
62 }
63 
64 void testException() {
65 #ifndef TEST_HAS_NO_EXCEPTIONS
66 
67   // int
68   {
69     const std::expected<int, int> e(std::unexpect, 5);
70     try {
71       (void) e.value();
72       assert(false);
73     } catch (const std::bad_expected_access<int>& ex) {
74       assert(ex.error() == 5);
75     }
76   }
77 
78 #endif // TEST_HAS_NO_EXCEPTIONS
79 }
80 
81 void testAsConst() {
82 #ifndef TEST_HAS_NO_EXCEPTIONS
83   struct Error {
84     enum { Default, MutableRefCalled, ConstRefCalled } From = Default;
85     Error()                                                 = default;
86     Error(const Error&) { From = ConstRefCalled; }
87     Error(Error&) { From = MutableRefCalled; }
88     Error(Error&& e) { From = e.From; }
89   };
90 
91   // Test & overload
92   {
93     std::expected<int, Error> e(std::unexpect, Error());
94     try {
95       (void)e.value();
96       assert(false);
97     } catch (const std::bad_expected_access<Error>& ex) {
98       assert(ex.error().From == Error::ConstRefCalled);
99     }
100   }
101 
102   // There are no effects for `const &` overload.
103 
104 #endif // TEST_HAS_NO_EXCEPTIONS
105 }
106 
107 int main(int, char**) {
108   test();
109   static_assert(test());
110   testException();
111   testAsConst();
112 
113   return 0;
114 }
115