// { dg-options "-std=gnu++17" }
// { dg-do run { target c++17 } }
// Copyright (C) 2013-2019 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// .
#include
#include
#include
using std::bad_optional_access;
static_assert( std::is_default_constructible::value, "" );
struct trivially_destructible
{
trivially_destructible() = delete;
trivially_destructible(trivially_destructible const&) = delete;
trivially_destructible& operator=(trivially_destructible const&) = delete;
trivially_destructible(trivially_destructible&&) = delete;
trivially_destructible& operator=(trivially_destructible&&) = delete;
~trivially_destructible() noexcept = default;
};
static_assert( std::is_trivially_destructible(), "" );
struct no_default_constructor
{
no_default_constructor() = delete;
};
struct no_copy_constructor
{
no_copy_constructor() = default;
no_copy_constructor(no_copy_constructor const&) = delete;
no_copy_constructor& operator=(no_copy_constructor const&) = default;
no_copy_constructor(no_copy_constructor&&) = default;
no_copy_constructor& operator=(no_copy_constructor&&) = default;
};
struct no_copy_assignment
{
no_copy_assignment() = default;
no_copy_assignment(no_copy_assignment const&) = default;
no_copy_assignment(no_copy_assignment&&) = default;
no_copy_assignment& operator=(no_copy_assignment&&) = default;
};
struct no_move_constructor
{
no_move_constructor() = default;
no_move_constructor(no_move_constructor const&) = default;
no_move_constructor& operator=(no_move_constructor const&) = default;
no_move_constructor(no_move_constructor&&) = delete;
no_move_constructor& operator=(no_move_constructor&&) = default;
};
struct no_move_assignment
{
no_move_assignment() = default;
no_move_assignment(no_move_assignment const&) = default;
no_move_assignment& operator=(no_move_assignment const&) = default;
no_move_assignment(no_move_assignment&&) = default;
no_move_assignment& operator=(no_move_assignment&&) = delete;
};
struct no_copy : no_copy_constructor, no_copy_assignment { };
struct no_move : no_move_constructor, no_move_assignment { };
// Laxest possible model of a value type for optional
struct only_destructible
{
only_destructible(only_destructible&&) = delete;
};
int main()
{
{
static_assert( std::is_trivially_destructible>(), "" );
}
{
using T = no_default_constructor;
using O = std::optional;
static_assert( std::is_same(), "" );
static_assert( std::is_default_constructible(), "" );
{ O o; }
static_assert( std::is_copy_constructible(), "" );
{ O o; auto copy = o; }
static_assert( std::is_copy_assignable(), "" );
{ O o, p; p = o; }
static_assert( std::is_move_constructible(), "" );
{ O o; auto moved_to = std::move(o); }
static_assert( std::is_move_assignable(), "" );
{ O o, p; p = std::move(o); }
}
{
using T = no_copy_constructor;
using O = std::optional;
static_assert( std::is_same(), "" );
static_assert( std::is_default_constructible(), "" );
{ O o; }
static_assert( !std::is_copy_constructible(), "" );
static_assert( !std::is_copy_assignable(), "" );
static_assert( std::is_move_constructible(), "" );
{ O o; auto moved_to = std::move(o); }
static_assert( std::is_move_assignable(), "" );
{ O o, p; p = std::move(o); }
}
{
using T = no_copy_assignment;
using O = std::optional;
static_assert( std::is_default_constructible(), "" );
{ O o; }
static_assert( std::is_copy_constructible(), "" );
{ O o; auto copy = o; }
static_assert( !std::is_copy_assignable(), "" );
static_assert( std::is_move_constructible(), "" );
{ O o; auto moved_to = std::move(o); }
static_assert( std::is_move_assignable(), "" );
{ O o, p; p = std::move(o); }
}
{
using T = no_copy;
using O = std::optional;
static_assert( std::is_same(), "" );
static_assert( std::is_default_constructible(), "" );
{ O o; }
static_assert( !std::is_copy_constructible(), "" );
static_assert( !std::is_copy_assignable(), "" );
static_assert( std::is_move_constructible(), "" );
{ O o; auto moved_to = std::move(o); }
static_assert( std::is_move_assignable(), "" );
{ O o, p; p = std::move(o); }
}
{
using T = no_move_constructor;
using O = std::optional;
static_assert( std::is_same(), "" );
static_assert( std::is_default_constructible(), "" );
{ O o; }
static_assert( std::is_copy_constructible(), "" );
{ O o; auto copy = o; }
static_assert( std::is_copy_assignable(), "" );
/*
* T should be move constructible due to [12.8/11], which is a new rule in C++1y
* not yet implemented by GCC. Because there is already a special exception in C++11
* for the generation of the special members that GCC implements (at least some of the
* time), this does not affect the std::optional implementation however. So the assertion
* for T should be changed (or removed altogether) when the time comes, but the rest
* should however remain correct and unchanged.
*/
static_assert( !std::is_move_constructible(), "" );
static_assert( std::is_move_constructible(), "" );
{ O o; auto moved_to = std::move(o); }
static_assert( std::is_move_assignable(), "" );
{ O o, p; p = std::move(o); }
}
{
using T = no_move_assignment;
using O = std::optional;
static_assert( std::is_same(), "" );
static_assert( std::is_default_constructible(), "" );
{ O o; }
static_assert( std::is_copy_constructible(), "" );
{ O o; auto copy = o; }
static_assert( std::is_copy_assignable(), "" );
{ O o, p; p = o; }
static_assert( std::is_move_constructible(), "" );
{ O o; auto moved_to = std::move(o); }
/*
* Paragraph 23 of same leads to a similar situation but with respect to move
* assignment.
*/
static_assert( !std::is_move_assignable(), "" );
static_assert( std::is_move_assignable(), "" );
{ O o, p; p = std::move(o); }
}
{
using T = no_move;
using O = std::optional;
static_assert( std::is_same(), "" );
static_assert( std::is_default_constructible(), "" );
{ O o; }
static_assert( std::is_copy_constructible(), "" );
{ O o; auto copy = o; }
static_assert( std::is_copy_assignable(), "" );
{ O o, p; p = o; }
static_assert( std::is_move_constructible(), "" );
{ O o; auto moved_to = std::move(o); }
static_assert( std::is_move_assignable(), "" );
{ O o, p; p = std::move(o); }
}
{
using T = only_destructible;
using O = std::optional;
static_assert( std::is_same(), "" );
static_assert( std::is_default_constructible(), "" );
{ O o; }
static_assert( !std::is_copy_constructible(), "" );
static_assert( !std::is_copy_assignable(), "" );
static_assert( !std::is_move_constructible(), "" );
static_assert( !std::is_move_assignable(), "" );
}
{
/*
* Should not complain about 'invalid' specializations as long as
* they're not instantiated.
*/
using A = std::optional;
using B = std::optional;
using C1 = std::optional;
using C2 = std::optional;
using C3 = std::optional;
using C4 = std::optional;
using D1 = std::optional;
using D2 = std::optional;
using D3 = std::optional;
using D4 = std::optional;
using X = std::tuple;
}
{
std::optional o { 42 };
static_assert( std::is_same(), "" );
VERIFY( o );
VERIFY( *o == 42 );
}
{
constexpr std::optional o { 33 };
static_assert( std::is_same(), "" );
static_assert( o, "" );
static_assert( *o == 33, "" );
}
}
using std::void_t;
using std::declval;
using std::true_type;
using std::false_type;
template
struct is_eq_comparable : false_type {};
template
struct is_eq_comparable() == declval())>>
: true_type {};
template
struct is_neq_comparable : false_type {};
template
struct is_neq_comparable() != declval())>>
: true_type {};
template
struct is_lt_comparable : false_type {};
template
struct is_lt_comparable() < declval())>>
: true_type {};
template
struct is_gt_comparable : false_type {};
template
struct is_gt_comparable() > declval())>>
: true_type {};
template
struct is_le_comparable : false_type {};
template
struct is_le_comparable() <= declval())>>
: true_type {};
template
struct is_ge_comparable : false_type {};
template
struct is_ge_comparable() >= declval())>>
: true_type {};
using std::optional;
static_assert(is_eq_comparable>::value, "");
static_assert(is_neq_comparable>::value, "");
static_assert(is_lt_comparable>::value, "");
static_assert(is_gt_comparable>::value, "");
static_assert(is_le_comparable>::value, "");
static_assert(is_ge_comparable>::value, "");
struct JustEq {};
bool operator==(const JustEq&, const JustEq&);
static_assert(is_eq_comparable>::value, "");
static_assert(!is_neq_comparable>::value, "");
static_assert(!is_lt_comparable>::value, "");
static_assert(!is_gt_comparable>::value, "");
static_assert(!is_le_comparable>::value, "");
static_assert(!is_ge_comparable>::value, "");
struct JustLt {};
bool operator<(const JustLt&, const JustLt&);
static_assert(!is_eq_comparable>::value, "");
static_assert(!is_neq_comparable>::value, "");
static_assert(is_lt_comparable>::value, "");
static_assert(!is_gt_comparable>::value, "");
static_assert(!is_le_comparable>::value, "");
static_assert(!is_ge_comparable>::value, "");
static_assert(!std::is_assignable&,
optional>::value, "");
static_assert(!std::is_assignable&,
JustLt>::value, "");
static_assert(!std::is_assignable&,
optional&>::value, "");
static_assert(!std::is_assignable&,
JustLt&>::value, "");