blob: 3aa2b9d92731fd5170860f12c61b044e49d1d625 [file] [log] [blame]
// { dg-do compile { target c++23 } }
// LWG 3938. Cannot use std::expected monadic ops with move-only error_type
#include <expected>
#include <testsuite_hooks.h>
struct MoveOnly {
constexpr MoveOnly(int i) : i(i) { }
constexpr MoveOnly(MoveOnly&&) = default;
constexpr MoveOnly(const MoveOnly&& mo) : i(mo.i) { }
constexpr bool operator==(const MoveOnly&) const = default;
int i;
};
constexpr bool
test_and_then()
{
auto fun = [](int i) { return std::expected<long, MoveOnly>(i); };
std::expected<int, MoveOnly> good(9);
std::expected<long, MoveOnly> e1 = std::move(good).and_then(fun);
VERIFY( e1 == good );
const auto& gooder = good;
std::expected<long, MoveOnly> e2 = std::move(gooder).and_then(fun);
VERIFY( e2 == gooder );
std::expected<int, MoveOnly> bad(std::unexpect, 99);
std::expected<long, MoveOnly> e3 = std::move(bad).and_then(fun);
VERIFY( e3 == bad );
const auto& badder = bad;
std::expected<long, MoveOnly> e4 = std::move(badder).and_then(fun);
VERIFY( e4 == badder );
auto vun = [] { return std::expected<long, MoveOnly>(1); };
std::expected<void, MoveOnly> vud;
std::expected<long, MoveOnly> e5 = std::move(vud).and_then(vun);
VERIFY( *e5 == 1 );
const auto& vudder = vud;
std::expected<long, MoveOnly> e6 = std::move(vudder).and_then(vun);
VERIFY( *e6 == 1 );
return true;
}
static_assert( test_and_then() );
constexpr bool
test_or_else()
{
auto fun = [](const MoveOnly&& mo) { return std::expected<int, long>(mo.i); };
std::expected<int, MoveOnly> good(9);
std::expected<int, long> e1 = std::move(good).or_else(fun);
VERIFY( e1 == good );
const auto& gooder = good;
std::expected<int, long> e2 = std::move(gooder).or_else(fun);
VERIFY( e2 == gooder );
std::expected<int, MoveOnly> bad(std::unexpect, 99);
std::expected<int, long> e3 = std::move(bad).or_else(fun);
VERIFY( *e3 == 99 );
const auto& badder = bad;
std::expected<int, long> e4 = std::move(badder).or_else(fun);
VERIFY( *e4 == 99 );
auto vun = [](const MoveOnly&& mo) { return std::expected<void, long>{}; };
std::expected<void, MoveOnly> vud;
std::expected<void, long> e5 = std::move(vud).or_else(vun);
VERIFY( e5.has_value() );
const auto& vudder = vud;
std::expected<void, long> e6 = std::move(vudder).or_else(vun);
VERIFY( e6.has_value() );
return true;
}
static_assert( test_or_else() );
constexpr bool
test_transform()
{
auto fun = [](int i) { return (long)i; };
std::expected<int, MoveOnly> good(9);
std::expected<long, MoveOnly> e1 = std::move(good).transform(fun);
VERIFY( e1 == good );
const auto& gooder = good;
std::expected<long, MoveOnly> e2 = std::move(gooder).transform(fun);
VERIFY( e2 == gooder );
std::expected<int, MoveOnly> bad(std::unexpect, 99);
std::expected<long, MoveOnly> e3 = std::move(bad).transform(fun);
VERIFY( e3 == bad );
const auto& badder = bad;
std::expected<long, MoveOnly> e4 = std::move(badder).transform(fun);
VERIFY( e4 == badder );
auto vun = []() { return 1L; };
std::expected<void, MoveOnly> vud;
std::expected<long, MoveOnly> e5 = std::move(vud).transform(vun);
VERIFY( *e5 == 1 );
const auto& vudder = vud;
std::expected<long, MoveOnly> e6 = std::move(vudder).transform(vun);
VERIFY( *e6 == 1 );
return true;
}
static_assert( test_transform() );
constexpr bool
test_transform_error()
{
auto fun = [](const MoveOnly&& mo) { return (long)mo.i; };
std::expected<int, MoveOnly> good(9);
std::expected<int, long> e1 = std::move(good).transform_error(fun);
VERIFY( e1 == good );
const auto& gooder = good;
std::expected<int, long> e2 = std::move(gooder).transform_error(fun);
VERIFY( e2 == gooder );
std::expected<int, MoveOnly> bad(std::unexpect, 99);
std::expected<int, long> e3 = std::move(bad).transform_error(fun);
VERIFY( e3.error() == 99 );
const auto& badder = bad;
std::expected<int, long> e4 = std::move(badder).transform_error(fun);
VERIFY( e4.error() == 99 );
std::expected<void, MoveOnly> vud(std::unexpect, 1);
std::expected<void, long> e5 = std::move(vud).transform_error(fun);
VERIFY( e5.error() == 1 );
const auto& vudder = vud;
std::expected<void, long> e6 = std::move(vudder).transform_error(fun);
VERIFY( e6.error() == 1 );
return true;
}
static_assert( test_transform_error() );