blob: 37c8ff355a6646e55b0817f70028a3eb83082c1d [file] [log] [blame]
// { dg-do run { target c++26 } }
#include <optional>
#include <type_traits>
#include <testsuite_hooks.h>
struct NonMovable
{
constexpr NonMovable() {}
NonMovable(NonMovable&&) = delete;
};
template<typename T>
constexpr
void test_value(T& t)
{
std::optional<T&> o1(t);
const std::optional<T&> co1(t);
static_assert( std::is_same_v<decltype(o1.value()), T&> );
VERIFY( &o1.value() == &t );
static_assert( std::is_same_v<decltype(co1.value()), T&> );
VERIFY( &co1.value() == &t );
static_assert( std::is_same_v<decltype(std::move(o1).value()), T&> );
VERIFY( &std::move(o1).value() == &t );
static_assert( std::is_same_v<decltype(std::move(co1).value()), T&> );
VERIFY( &std::move(co1).value() == &t );
std::optional<const T&> o2(t);
static_assert( std::is_same_v<decltype(o2.value()), const T&> );
VERIFY( &o2.value() == &t );
}
struct Tracker
{
int copy = 0;
int move = 0;
constexpr Tracker(int v) : copy(v), move(v) {}
constexpr Tracker(Tracker const& o)
: copy(o.copy+1), move(o.move)
{}
constexpr Tracker(Tracker&& o)
: copy(o.copy), move(o.move+1)
{}
Tracker& operator=(Tracker) = delete;
};
constexpr
void test_value_or()
{
Tracker t(100), u(200);
std::optional<Tracker&> o(t);
Tracker r1 = o.value_or(u);
VERIFY( r1.copy == 101 );
VERIFY( r1.move == 100 );
Tracker r2 = o.value_or(std::move(u));
VERIFY( r2.copy == 101 );
VERIFY( r2.move == 100 );
Tracker r3 = std::move(o).value_or(u);
VERIFY( r3.copy == 101 );
VERIFY( r3.move == 100 );
Tracker r4 = std::move(o).value_or(std::move(u));
VERIFY( r4.copy == 101 );
VERIFY( r4.move == 100 );
o.reset();
Tracker r5 = o.value_or(u);
VERIFY( r5.copy == 201 );
VERIFY( r5.move == 200 );
Tracker r6 = o.value_or(std::move(u));
VERIFY( r6.copy == 200 );
VERIFY( r6.move == 201 );
Tracker r7 = std::move(o).value_or(u);
VERIFY( r7.copy == 201 );
VERIFY( r7.move == 200 );
Tracker r8 = std::move(o).value_or(std::move(u));
VERIFY( r8.copy == 200 );
VERIFY( r8.move == 201 );
}
template<typename T>
concept has_value_or_for = requires(std::optional<T&> t, T& u)
{ t.value_or(u); };
static_assert( has_value_or_for<int> );
static_assert( has_value_or_for<NonMovable> );
static_assert( !has_value_or_for<int[2]> );
static_assert( has_value_or_for<int(*)[2]> );
static_assert( !has_value_or_for<int()> );
static_assert( has_value_or_for<int(*)()> );
int i;
NonMovable nm;
int arr[2];
int foo();
int main()
{
auto test_all = [] {
test_value<int>(i);
test_value<NonMovable>(nm);
test_value<int[2]>(arr);
test_value<int()>(foo);
test_value_or();
return true;
};
test_all();
static_assert(test_all());
}