- Collapse the different ref/const-qualifier `operator*`, `operator->` and `value()` tests since they were all very similar to each other - Refactor them to be inline with the current testing style
178 lines
4.4 KiB
C++
178 lines
4.4 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|
|
|
|
// <optional>
|
|
|
|
// constexpr T& optional<T>::value() &;
|
|
// constexpr const T& optional<T>::value() const&;
|
|
// constexpr T&& optional<T>::value() &&;
|
|
// constexpr const T&& optional<T>::value() const T&&;
|
|
// constexpr T& optional<T&>::value() const;
|
|
|
|
#include <cassert>
|
|
#include <optional>
|
|
#include <utility>
|
|
|
|
#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 <typename T>
|
|
constexpr void test_contract() {
|
|
std::optional<T> 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 <typename T>
|
|
constexpr void test_ref_contract() {
|
|
std::optional<T&> 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<int>();
|
|
test_contract<float>();
|
|
test_contract<double>();
|
|
test_contract<X>();
|
|
|
|
test_contract<const int>();
|
|
test_contract<const float>();
|
|
test_contract<const double>();
|
|
test_contract<const X>();
|
|
|
|
{
|
|
std::optional<X> 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<int>();
|
|
test_ref_contract<float>();
|
|
test_ref_contract<double>();
|
|
test_ref_contract<X>();
|
|
|
|
test_ref_contract<const int>();
|
|
test_ref_contract<const float>();
|
|
test_ref_contract<const double>();
|
|
test_ref_contract<const X>();
|
|
|
|
{
|
|
X x;
|
|
std::optional<X&> 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<const X&> 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<X> 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<X> 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;
|
|
}
|