//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14 // // constexpr T& optional::value() &; // constexpr const T& optional::value() const&; // constexpr T&& optional::value() &&; // constexpr const T&& optional::value() const T&&; // constexpr T& optional::value() const; #include #include #include #include "test_macros.h" struct X { constexpr X() = default; constexpr int test() const& { return 3; } constexpr int test() & { return 4; } constexpr int test() const&& { return 5; } constexpr int test() && { return 6; } }; template constexpr void test_contract() { std::optional opt; ASSERT_SAME_TYPE(decltype(opt.value()), T&); ASSERT_SAME_TYPE(decltype(std::as_const(opt).value()), const T&); ASSERT_SAME_TYPE(decltype(std::move(opt).value()), T&&); ASSERT_SAME_TYPE(decltype(std::move(std::as_const(opt)).value()), const T&&); ASSERT_NOT_NOEXCEPT(opt.value()); ASSERT_NOT_NOEXCEPT(std::as_const(opt).value()); ASSERT_NOT_NOEXCEPT(std::move(opt).value()); ASSERT_NOT_NOEXCEPT(std::move(std::as_const(opt)).value()); } #if TEST_STD_VER >= 26 template constexpr void test_ref_contract() { std::optional opt; ASSERT_SAME_TYPE(decltype(opt.value()), T&); ASSERT_SAME_TYPE(decltype(std::as_const(opt).value()), T&); ASSERT_SAME_TYPE(decltype(std::move(opt).value()), T&); ASSERT_SAME_TYPE(decltype(std::move(std::as_const(opt)).value()), T&); ASSERT_NOT_NOEXCEPT(opt.value()); ASSERT_NOT_NOEXCEPT(std::as_const(opt).value()); ASSERT_NOT_NOEXCEPT(std::move(opt).value()); ASSERT_NOT_NOEXCEPT(std::move(std::as_const(opt)).value()); } #endif constexpr bool test() { test_contract(); test_contract(); test_contract(); test_contract(); test_contract(); test_contract(); test_contract(); test_contract(); { std::optional opt(X{}); assert(std::as_const(opt).value().test() == 3); assert(opt.value().test() == 4); assert(std::move(std::as_const(opt)).value().test() == 5); assert(std::move(opt).value().test() == 6); } #if TEST_STD_VER >= 26 test_ref_contract(); test_ref_contract(); test_ref_contract(); test_ref_contract(); test_ref_contract(); test_ref_contract(); test_ref_contract(); test_ref_contract(); { X x; std::optional o1{x}; assert(o1.value().test() == 4); assert(std::as_const(o1).value().test() == 4); assert(std::move(o1).value().test() == 4); assert(std::move(std::as_const(o1)).value().test() == 4); } { X x; std::optional o2{x}; assert(o2.value().test() == 3); assert(std::as_const(o2).value().test() == 3); assert(std::move(o2).value().test() == 3); assert(std::move(std::as_const(o2)).value().test() == 3); } #endif return true; } int main(int, char**) { assert(test()); static_assert(test()); #ifndef TEST_HAS_NO_EXCEPTIONS { std::optional opt; try { (void)opt.value(); assert(false); } catch (const std::bad_optional_access&) { } try { (void)std::as_const(opt).value(); assert(false); } catch (const std::bad_optional_access&) { } try { (void)std::move(opt).value(); assert(false); } catch (const std::bad_optional_access&) { } try { (void)std::move(std::as_const(opt)).value(); assert(false); } catch (const std::bad_optional_access&) { } } { std::optional opt(X{}); try { (void)opt.value(); } catch (const std::bad_optional_access&) { assert(false); } try { (void)std::as_const(opt).value(); } catch (const std::bad_optional_access&) { assert(false); } try { (void)std::move(opt).value(); } catch (const std::bad_optional_access&) { assert(false); } try { (void)std::move(std::as_const(opt)).value(); } catch (const std::bad_optional_access&) { assert(false); } } #endif return 0; }