mirror of git://gcc.gnu.org/git/gcc.git
238 lines
4.8 KiB
C++
238 lines
4.8 KiB
C++
// { dg-do run { target c++23 } }
|
|
|
|
#include <expected>
|
|
#include <expected>
|
|
#include <testsuite_hooks.h>
|
|
|
|
struct X
|
|
{
|
|
constexpr int f() & { return 1; }
|
|
constexpr int f() const & { return 2; }
|
|
constexpr int f() && { return 3; }
|
|
constexpr int f() const && { return 4; }
|
|
};
|
|
|
|
constexpr bool
|
|
test_arrow()
|
|
{
|
|
std::expected<X, int> e1;
|
|
VERIFY( e1->f() == 1 );
|
|
const auto& e2 = e1;
|
|
VERIFY( e2->f() == 2 );
|
|
|
|
return true;
|
|
}
|
|
|
|
constexpr bool
|
|
test_star()
|
|
{
|
|
std::expected<X, int> e1;
|
|
VERIFY( (*e1).f() == 1 );
|
|
VERIFY( std::move(*e1).f() == 3 );
|
|
const auto& e2 = e1;
|
|
VERIFY( (*e2).f() == 2 );
|
|
VERIFY( std::move(*e2).f() == 4 );
|
|
|
|
std::expected<void, int> v;
|
|
*v;
|
|
|
|
return true;
|
|
}
|
|
|
|
constexpr bool
|
|
test_has_value()
|
|
{
|
|
std::expected<int, int> e;
|
|
VERIFY( e.has_value() );
|
|
VERIFY( e );
|
|
e = std::unexpected(1);
|
|
VERIFY( ! e.has_value() );
|
|
VERIFY( ! e );
|
|
|
|
std::expected<void, int> v;
|
|
VERIFY( v.has_value() );
|
|
VERIFY( v );
|
|
v = std::unexpected(1);
|
|
VERIFY( ! v.has_value() );
|
|
VERIFY( ! v );
|
|
|
|
return true;
|
|
}
|
|
|
|
constexpr bool
|
|
test_value()
|
|
{
|
|
std::expected<X, int> e1;
|
|
|
|
VERIFY( e1.value().f() == 1 );
|
|
VERIFY( std::move(e1).value().f() == 3 );
|
|
const auto& e2 = e1;
|
|
VERIFY( e2.value().f() == 2 );
|
|
VERIFY( std::move(e2).value().f() == 4 );
|
|
|
|
std::expected<void, int> v1;
|
|
v1.value();
|
|
std::move(v1).value();
|
|
|
|
return true;
|
|
}
|
|
|
|
#if __cpp_lib_constexpr_exceptions >= 202502L
|
|
constexpr
|
|
#endif
|
|
bool
|
|
test_value_throw()
|
|
{
|
|
std::expected<int, int> e1 = std::unexpected(9);
|
|
|
|
try {
|
|
e1.value();
|
|
VERIFY( false );
|
|
} catch (const std::bad_expected_access<int>& e) {
|
|
VERIFY( e.error() == 9 );
|
|
long c = e.what()[0];
|
|
VERIFY( c == e.what()[0] );
|
|
}
|
|
try {
|
|
std::move(e1).value();
|
|
VERIFY( false );
|
|
} catch (const std::bad_expected_access<int>& e) {
|
|
VERIFY( e.error() == 9 );
|
|
}
|
|
|
|
const auto& e2 = e1;
|
|
try {
|
|
e2.value();
|
|
VERIFY( false );
|
|
} catch (const std::bad_expected_access<int>& e) {
|
|
VERIFY( e.error() == 9 );
|
|
}
|
|
try {
|
|
std::move(e2).value();
|
|
VERIFY( false );
|
|
} catch (const std::bad_expected_access<int>& e) {
|
|
VERIFY( e.error() == 9 );
|
|
}
|
|
|
|
std::expected<void, int> v1 = std::unexpected(8);
|
|
try {
|
|
v1.value();
|
|
VERIFY( false );
|
|
} catch (const std::bad_expected_access<int>& e) {
|
|
VERIFY( e.error() == 8 );
|
|
}
|
|
try {
|
|
std::move(v1).value();
|
|
VERIFY( false );
|
|
} catch (const std::bad_expected_access<int>& e) {
|
|
VERIFY( e.error() == 8 );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
constexpr bool
|
|
test_error()
|
|
{
|
|
std::expected<int, X> e1(std::unexpect);
|
|
|
|
VERIFY( e1.error().f() == 1 );
|
|
VERIFY( std::move(e1).error().f() == 3 );
|
|
const auto& e2 = e1;
|
|
VERIFY( e2.error().f() == 2 );
|
|
VERIFY( std::move(e2).error().f() == 4 );
|
|
|
|
std::expected<void, X> v1(std::unexpect);
|
|
|
|
VERIFY( v1.error().f() == 1 );
|
|
VERIFY( std::move(v1).error().f() == 3 );
|
|
const auto& v2 = v1;
|
|
VERIFY( v2.error().f() == 2 );
|
|
VERIFY( std::move(v2).error().f() == 4 );
|
|
|
|
return true;
|
|
}
|
|
|
|
constexpr bool
|
|
test_value_or()
|
|
{
|
|
struct Movable
|
|
{
|
|
constexpr Movable(int i) : x(i) { }
|
|
constexpr Movable(const Movable&) = default;
|
|
constexpr Movable(Movable&& m) : x(m.x) { m.x = -1; }
|
|
int x;
|
|
|
|
constexpr bool operator==(int i) const { return x == i; }
|
|
};
|
|
|
|
std::expected<Movable, int> e1(1);
|
|
|
|
Movable m2(2);
|
|
VERIFY( e1.value_or(2) == 1 );
|
|
VERIFY( e1.value_or(m2) == 1 );
|
|
VERIFY( e1.value_or(std::move(m2)) == 1 );
|
|
VERIFY( m2 == 2 );
|
|
|
|
VERIFY( std::move(e1).value_or(m2) == 1 );
|
|
VERIFY( *e1 == -1 ); // moved
|
|
VERIFY( m2 == 2 );
|
|
|
|
e1 = std::unexpected(3);
|
|
VERIFY( e1.value_or(m2) == 2 );
|
|
VERIFY( m2 == 2 );
|
|
VERIFY( std::move(e1).value_or(m2) == 2 );
|
|
VERIFY( m2 == 2 );
|
|
|
|
VERIFY( e1.value_or(std::move(m2)) == 2 );
|
|
VERIFY( m2 == -1 );
|
|
|
|
m2.x = 4;
|
|
VERIFY( std::move(e1).value_or(std::move(m2)) == 4 );
|
|
VERIFY( m2 == -1 );
|
|
|
|
VERIFY( e1.value_or(5) == 5 );
|
|
VERIFY( std::move(e1).value_or(6) == 6 );
|
|
|
|
return true;
|
|
}
|
|
|
|
constexpr bool
|
|
test_error_or()
|
|
{
|
|
std::expected<int, int> e1(1), e2(std::unexpect, 3);
|
|
VERIFY( e1.error_or(2) == 2 );
|
|
VERIFY( std::move(e1).error_or(2) == 2 );
|
|
VERIFY( e2.error_or(2) == 3 );
|
|
VERIFY( std::move(e2).error_or(2) == 3 );
|
|
|
|
std::expected<void, int> e3, e4(std::unexpect, 3);
|
|
VERIFY( e3.error_or(2) == 2 );
|
|
VERIFY( std::move(e3).error_or(2) == 2 );
|
|
VERIFY( e4.error_or(2) == 3 );
|
|
VERIFY( std::move(e4).error_or(2) == 3 );
|
|
|
|
return true;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
static_assert( test_arrow() );
|
|
test_arrow();
|
|
static_assert( test_star() );
|
|
test_star();
|
|
static_assert( test_has_value() );
|
|
test_has_value();
|
|
static_assert( test_value() );
|
|
test_value();
|
|
#if __cpp_lib_constexpr_exceptions >= 202502L
|
|
static_assert( test_value_throw() );
|
|
#endif
|
|
test_value_throw();
|
|
static_assert( test_error() );
|
|
test_error();
|
|
static_assert( test_value_or() );
|
|
test_value_or();
|
|
static_assert( test_error_or() );
|
|
test_error_or();
|
|
}
|