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