[libcxx][optional] adds missing constexpr operations
Makes the following operations constexpr: * `std::swap(optional, optional)` * `optional(optional<U> const&)` * `optional(optional<U>&&)` * `~optional()` * `operator=(nullopt_t)` * `operator=(U&&)` * `operator=(optional<U> const&)` * `operator=(optional<U>&&)` * `emplace(Args&&...)` * `emplace(initializer_list<U>, Args&&...)` * `swap(optional&)` * `reset()` P2231 has been accepted by plenary, with the committee recommending implementers retroactively apply to C++20. It's necessary for us to implement _`semiregular-box`_ and _`non-propagating-cache`_, both of which are required for ranges (otherwise we'll need to reimplement `std::optional` with these members `constexpr`ified). Differential Revision: https://reviews.llvm.org/D102119
This commit is contained in:
parent
b5d6da3587
commit
546449938a
|
@ -193,3 +193,4 @@
|
|||
"`P2102 <https://wg21.link/P2102>`__","LWG","Make 'implicit expression variations' more explicit (Wording for US185)","Prague","* *",""
|
||||
"`P2106 <https://wg21.link/P2106>`__","LWG","Alternative wording for GB315 and GB316","Prague","* *",""
|
||||
"`P2116 <https://wg21.link/P2116>`__","LWG","Remove tuple-like protocol support from fixed-extent span","Prague","|Complete|","11.0"
|
||||
"`P2231 <https://wg21.link/P2231>`__","LWG","Missing constexpr in std::optional and std::variant","February 2021","|In progress|","13.0"
|
||||
|
|
|
|
@ -69,7 +69,7 @@ namespace std {
|
|||
template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
|
||||
|
||||
// 23.6.9, specialized algorithms
|
||||
template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below );
|
||||
template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
|
||||
template <class T> constexpr optional<see below > make_optional(T&&);
|
||||
template <class T, class... Args>
|
||||
constexpr optional<T> make_optional(Args&&... args);
|
||||
|
@ -95,26 +95,26 @@ namespace std {
|
|||
template <class U = T>
|
||||
constexpr EXPLICIT optional(U &&);
|
||||
template <class U>
|
||||
constexpr EXPLICIT optional(const optional<U> &);
|
||||
EXPLICIT optional(const optional<U> &); // constexpr in C++20
|
||||
template <class U>
|
||||
constexpr EXPLICIT optional(optional<U> &&);
|
||||
EXPLICIT optional(optional<U> &&); // constexpr in C++20
|
||||
|
||||
// 23.6.3.2, destructor
|
||||
~optional();
|
||||
~optional(); // constexpr in C++20
|
||||
|
||||
// 23.6.3.3, assignment
|
||||
optional &operator=(nullopt_t) noexcept;
|
||||
optional &operator=(const optional &); // constexpr in C++20
|
||||
optional &operator=(optional &&) noexcept(see below); // constexpr in C++20
|
||||
template <class U = T> optional &operator=(U &&);
|
||||
template <class U> optional &operator=(const optional<U> &);
|
||||
template <class U> optional &operator=(optional<U> &&);
|
||||
template <class... Args> T& emplace(Args &&...);
|
||||
optional &operator=(nullopt_t) noexcept; // constexpr in C++20
|
||||
optional &operator=(const optional &); // constexpr in C++20
|
||||
optional &operator=(optional &&) noexcept(see below); // constexpr in C++20
|
||||
template <class U = T> optional &operator=(U &&); // constexpr in C++20
|
||||
template <class U> optional &operator=(const optional<U> &); // constexpr in C++20
|
||||
template <class U> optional &operator=(optional<U> &&); // constexpr in C++20
|
||||
template <class... Args> T& emplace(Args &&...); // constexpr in C++20
|
||||
template <class U, class... Args>
|
||||
T& emplace(initializer_list<U>, Args &&...);
|
||||
T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20
|
||||
|
||||
// 23.6.3.4, swap
|
||||
void swap(optional &) noexcept(see below );
|
||||
void swap(optional &) noexcept(see below ); // constexpr in C++20
|
||||
|
||||
// 23.6.3.5, observers
|
||||
constexpr T const *operator->() const;
|
||||
|
@ -133,7 +133,7 @@ namespace std {
|
|||
template <class U> constexpr T value_or(U &&) &&;
|
||||
|
||||
// 23.6.3.6, modifiers
|
||||
void reset() noexcept;
|
||||
void reset() noexcept; // constexpr in C++20
|
||||
|
||||
private:
|
||||
T *val; // exposition only
|
||||
|
@ -221,7 +221,7 @@ struct __optional_destruct_base<_Tp, false>
|
|||
bool __engaged_;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
~__optional_destruct_base()
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
|
||||
{
|
||||
if (__engaged_)
|
||||
__val_.~value_type();
|
||||
|
@ -239,7 +239,7 @@ struct __optional_destruct_base<_Tp, false>
|
|||
__engaged_(true) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void reset() noexcept
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
|
||||
{
|
||||
if (__engaged_)
|
||||
{
|
||||
|
@ -274,7 +274,7 @@ struct __optional_destruct_base<_Tp, true>
|
|||
__engaged_(true) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void reset() noexcept
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
|
||||
{
|
||||
if (__engaged_)
|
||||
{
|
||||
|
@ -319,16 +319,20 @@ struct __optional_storage_base : __optional_destruct_base<_Tp>
|
|||
|
||||
template <class... _Args>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __construct(_Args&&... __args)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args)
|
||||
{
|
||||
_LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
_VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
|
||||
#else
|
||||
::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
|
||||
#endif
|
||||
this->__engaged_ = true;
|
||||
}
|
||||
|
||||
template <class _That>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __construct_from(_That&& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
|
||||
{
|
||||
if (__opt.has_value())
|
||||
__construct(_VSTD::forward<_That>(__opt).__get());
|
||||
|
@ -336,7 +340,7 @@ struct __optional_storage_base : __optional_destruct_base<_Tp>
|
|||
|
||||
template <class _That>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __assign_from(_That&& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
|
||||
{
|
||||
if (this->__engaged_ == __opt.has_value())
|
||||
{
|
||||
|
@ -394,7 +398,7 @@ struct __optional_storage_base<_Tp, true>
|
|||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void reset() noexcept { __value_ = nullptr; }
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
constexpr bool has_value() const noexcept
|
||||
|
@ -410,7 +414,7 @@ struct __optional_storage_base<_Tp, true>
|
|||
|
||||
template <class _UArg>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __construct(_UArg&& __val)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val)
|
||||
{
|
||||
_LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
|
||||
static_assert(__can_bind_reference<_UArg>(),
|
||||
|
@ -421,7 +425,7 @@ struct __optional_storage_base<_Tp, true>
|
|||
|
||||
template <class _That>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __construct_from(_That&& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
|
||||
{
|
||||
if (__opt.has_value())
|
||||
__construct(_VSTD::forward<_That>(__opt).__get());
|
||||
|
@ -429,7 +433,7 @@ struct __optional_storage_base<_Tp, true>
|
|||
|
||||
template <class _That>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __assign_from(_That&& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
|
||||
{
|
||||
if (has_value() == __opt.has_value())
|
||||
{
|
||||
|
@ -461,7 +465,7 @@ struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
|
|||
__optional_copy_base() = default;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__optional_copy_base(const __optional_copy_base& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt)
|
||||
{
|
||||
this->__construct_from(__opt);
|
||||
}
|
||||
|
@ -492,7 +496,7 @@ struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
|
|||
__optional_move_base(const __optional_move_base&) = default;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__optional_move_base(__optional_move_base&& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt)
|
||||
noexcept(is_nothrow_move_constructible_v<value_type>)
|
||||
{
|
||||
this->__construct_from(_VSTD::move(__opt));
|
||||
|
@ -526,7 +530,7 @@ struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
|
|||
__optional_copy_assign_base(__optional_copy_assign_base&&) = default;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
|
||||
{
|
||||
this->__assign_from(__opt);
|
||||
return *this;
|
||||
|
@ -561,7 +565,7 @@ struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp
|
|||
__optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
|
||||
noexcept(is_nothrow_move_assignable_v<value_type> &&
|
||||
is_nothrow_move_constructible_v<value_type>)
|
||||
{
|
||||
|
@ -728,7 +732,7 @@ public:
|
|||
_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
|
||||
, int> = 0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
optional(const optional<_Up>& __v)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v)
|
||||
{
|
||||
this->__construct_from(__v);
|
||||
}
|
||||
|
@ -736,7 +740,7 @@ public:
|
|||
_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
|
||||
, int> = 0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit optional(const optional<_Up>& __v)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v)
|
||||
{
|
||||
this->__construct_from(__v);
|
||||
}
|
||||
|
@ -746,7 +750,7 @@ public:
|
|||
_CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
|
||||
, int> = 0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
optional(optional<_Up>&& __v)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v)
|
||||
{
|
||||
this->__construct_from(_VSTD::move(__v));
|
||||
}
|
||||
|
@ -754,13 +758,13 @@ public:
|
|||
_CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
|
||||
, int> = 0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit optional(optional<_Up>&& __v)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v)
|
||||
{
|
||||
this->__construct_from(_VSTD::move(__v));
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
optional& operator=(nullopt_t) noexcept
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
|
@ -783,7 +787,7 @@ public:
|
|||
>::value>
|
||||
>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
optional&
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
|
||||
operator=(_Up&& __v)
|
||||
{
|
||||
if (this->has_value())
|
||||
|
@ -798,7 +802,7 @@ public:
|
|||
_CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
|
||||
, int> = 0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
optional&
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
|
||||
operator=(const optional<_Up>& __v)
|
||||
{
|
||||
this->__assign_from(__v);
|
||||
|
@ -810,7 +814,7 @@ public:
|
|||
_CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
|
||||
, int> = 0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
optional&
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
|
||||
operator=(optional<_Up>&& __v)
|
||||
{
|
||||
this->__assign_from(_VSTD::move(__v));
|
||||
|
@ -824,7 +828,7 @@ public:
|
|||
>
|
||||
>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_Tp &
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
|
||||
emplace(_Args&&... __args)
|
||||
{
|
||||
reset();
|
||||
|
@ -839,7 +843,7 @@ public:
|
|||
>
|
||||
>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_Tp &
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
|
||||
emplace(initializer_list<_Up> __il, _Args&&... __args)
|
||||
{
|
||||
reset();
|
||||
|
@ -848,7 +852,7 @@ public:
|
|||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void swap(optional& __opt)
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt)
|
||||
noexcept(is_nothrow_move_constructible_v<value_type> &&
|
||||
is_nothrow_swappable_v<value_type>)
|
||||
{
|
||||
|
@ -1006,7 +1010,7 @@ public:
|
|||
private:
|
||||
template <class _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static _Up*
|
||||
static _LIBCPP_CONSTEXPR_AFTER_CXX17 _Up*
|
||||
__operator_arrow(true_type, _Up& __x)
|
||||
{
|
||||
return _VSTD::addressof(__x);
|
||||
|
@ -1367,7 +1371,7 @@ operator>=(const _Tp& __v, const optional<_Up>& __x)
|
|||
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
_EnableIf<
|
||||
is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
|
||||
void
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// UNSUPPORTED: gcc-10
|
||||
// <optional>
|
||||
|
||||
// template <class... Args> T& optional<T>::emplace(Args&&... args);
|
||||
|
@ -26,11 +27,11 @@ class X
|
|||
int i_;
|
||||
int j_ = 0;
|
||||
public:
|
||||
X() : i_(0) {}
|
||||
X(int i) : i_(i) {}
|
||||
X(int i, int j) : i_(i), j_(j) {}
|
||||
constexpr X() : i_(0) {}
|
||||
constexpr X(int i) : i_(i) {}
|
||||
constexpr X(int i, int j) : i_(i), j_(j) {}
|
||||
|
||||
friend bool operator==(const X& x, const X& y)
|
||||
constexpr friend bool operator==(const X& x, const X& y)
|
||||
{return x.i_ == y.i_ && x.j_ == y.j_;}
|
||||
};
|
||||
|
||||
|
@ -46,7 +47,7 @@ public:
|
|||
bool Y::dtor_called = false;
|
||||
|
||||
template <class T>
|
||||
void test_one_arg() {
|
||||
constexpr bool test_one_arg() {
|
||||
using Opt = std::optional<T>;
|
||||
{
|
||||
Opt opt;
|
||||
|
@ -80,11 +81,12 @@ void test_one_arg() {
|
|||
assert(*opt == T(1));
|
||||
assert(&v == &*opt);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
void test_multi_arg()
|
||||
constexpr bool test_multi_arg()
|
||||
{
|
||||
test_one_arg<T>();
|
||||
using Opt = std::optional<T>;
|
||||
|
@ -112,6 +114,7 @@ void test_multi_arg()
|
|||
assert( v == T(5)); // T sets its value to the size of the init list
|
||||
assert(*opt == T(5)); // T sets its value to the size of the init list
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
@ -206,7 +209,17 @@ void test_on_test_type() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
constexpr bool test_empty_emplace()
|
||||
{
|
||||
optional<const int> opt;
|
||||
auto &v = opt.emplace(42);
|
||||
static_assert( std::is_same_v<const int&, decltype(v)>, "" );
|
||||
assert(*opt == 42);
|
||||
assert( v == 42);
|
||||
opt.emplace();
|
||||
assert(*opt == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
|
@ -218,31 +231,44 @@ int main(int, char**)
|
|||
using T = int;
|
||||
test_one_arg<T>();
|
||||
test_one_arg<const T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_one_arg<T>());
|
||||
static_assert(test_one_arg<const T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = ConstexprTestTypes::TestType;
|
||||
test_multi_arg<T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_multi_arg<T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = ExplicitConstexprTestTypes::TestType;
|
||||
test_multi_arg<T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_multi_arg<T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = TrivialTestTypes::TestType;
|
||||
test_multi_arg<T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_multi_arg<T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = ExplicitTrivialTestTypes::TestType;
|
||||
test_multi_arg<T>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_multi_arg<T>());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
optional<const int> opt;
|
||||
auto &v = opt.emplace(42);
|
||||
static_assert( std::is_same_v<const int&, decltype(v)>, "" );
|
||||
assert(*opt == 42);
|
||||
assert( v == 42);
|
||||
opt.emplace();
|
||||
assert(*opt == 0);
|
||||
test_empty_emplace();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_empty_emplace());
|
||||
#endif
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
Y::dtor_called = false;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// UNSUPPORTED: gcc-10
|
||||
// <optional>
|
||||
|
||||
// template <class U, class... Args>
|
||||
|
@ -25,19 +26,18 @@ class X
|
|||
{
|
||||
int i_;
|
||||
int j_ = 0;
|
||||
bool* dtor_called_;
|
||||
public:
|
||||
static bool dtor_called;
|
||||
constexpr X() : i_(0) {}
|
||||
constexpr X(int i) : i_(i) {}
|
||||
constexpr X(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
|
||||
~X() {dtor_called = true;}
|
||||
constexpr X(bool& dtor_called) : i_(0), dtor_called_(&dtor_called) {}
|
||||
constexpr X(int i, bool& dtor_called) : i_(i), dtor_called_(&dtor_called) {}
|
||||
constexpr X(std::initializer_list<int> il, bool& dtor_called)
|
||||
: i_(il.begin()[0]), j_(il.begin()[1]), dtor_called_(&dtor_called) {}
|
||||
TEST_CONSTEXPR_CXX20 ~X() {*dtor_called_ = true;}
|
||||
|
||||
friend constexpr bool operator==(const X& x, const X& y)
|
||||
{return x.i_ == y.i_ && x.j_ == y.j_;}
|
||||
};
|
||||
|
||||
bool X::dtor_called = false;
|
||||
|
||||
class Y
|
||||
{
|
||||
int i_;
|
||||
|
@ -69,17 +69,38 @@ public:
|
|||
|
||||
bool Z::dtor_called = false;
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool check_X()
|
||||
{
|
||||
bool dtor_called = false;
|
||||
X x(dtor_called);
|
||||
optional<X> opt(x);
|
||||
assert(dtor_called == false);
|
||||
auto &v = opt.emplace({1, 2}, dtor_called);
|
||||
static_assert( std::is_same_v<X&, decltype(v)>, "" );
|
||||
assert(dtor_called);
|
||||
assert(*opt == X({1, 2}, dtor_called));
|
||||
assert(&v == &*opt);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool check_Y()
|
||||
{
|
||||
optional<Y> opt;
|
||||
auto &v = opt.emplace({1, 2});
|
||||
static_assert( std::is_same_v<Y&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == Y({1, 2}));
|
||||
assert(&v == &*opt);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
X x;
|
||||
optional<X> opt(x);
|
||||
assert(X::dtor_called == false);
|
||||
auto &v = opt.emplace({1, 2});
|
||||
static_assert( std::is_same_v<X&, decltype(v)>, "" );
|
||||
assert(X::dtor_called == true);
|
||||
assert(*opt == X({1, 2}));
|
||||
assert(&v == &*opt);
|
||||
check_X();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(check_X());
|
||||
#endif
|
||||
}
|
||||
{
|
||||
optional<std::vector<int>> opt;
|
||||
|
@ -90,12 +111,10 @@ int main(int, char**)
|
|||
assert(&v == &*opt);
|
||||
}
|
||||
{
|
||||
optional<Y> opt;
|
||||
auto &v = opt.emplace({1, 2});
|
||||
static_assert( std::is_same_v<Y&, decltype(v)>, "" );
|
||||
assert(static_cast<bool>(opt) == true);
|
||||
assert(*opt == Y({1, 2}));
|
||||
assert(&v == &*opt);
|
||||
check_Y();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(check_Y());
|
||||
#endif
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
|
|
|
@ -22,8 +22,21 @@ using std::optional;
|
|||
using std::nullopt_t;
|
||||
using std::nullopt;
|
||||
|
||||
int main(int, char**)
|
||||
TEST_CONSTEXPR_CXX20 bool test()
|
||||
{
|
||||
enum class State { inactive, constructed, destroyed };
|
||||
State state = State::inactive;
|
||||
|
||||
struct StateTracker {
|
||||
TEST_CONSTEXPR_CXX20 StateTracker(State& s)
|
||||
: state_(&s)
|
||||
{
|
||||
s = State::constructed;
|
||||
}
|
||||
TEST_CONSTEXPR_CXX20 ~StateTracker() { *state_ = State::destroyed; }
|
||||
|
||||
State* state_;
|
||||
};
|
||||
{
|
||||
optional<int> opt;
|
||||
static_assert(noexcept(opt = nullopt) == true, "");
|
||||
|
@ -35,6 +48,29 @@ int main(int, char**)
|
|||
opt = nullopt;
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
{
|
||||
optional<StateTracker> opt;
|
||||
opt = nullopt;
|
||||
assert(state == State::inactive);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
{
|
||||
optional<StateTracker> opt(state);
|
||||
assert(state == State::constructed);
|
||||
opt = nullopt;
|
||||
assert(state == State::destroyed);
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test());
|
||||
#endif
|
||||
test();
|
||||
using TT = TestTypes::TestType;
|
||||
TT::reset();
|
||||
{
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
// optional<T>& operator=(optional<U>&& rhs);
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "archetypes.h"
|
||||
|
@ -201,42 +203,109 @@ void test_ambiguous_assign() {
|
|||
}
|
||||
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test()
|
||||
{
|
||||
{
|
||||
optional<int> opt;
|
||||
optional<short> opt2;
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt;
|
||||
optional<short> opt2(short{2});
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
optional<short> opt2;
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
optional<short> opt2(short{2});
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
|
||||
enum class state_t { inactive, constructed, copy_assigned, move_assigned };
|
||||
class StateTracker {
|
||||
public:
|
||||
constexpr StateTracker(state_t& s)
|
||||
: state_(&s)
|
||||
{
|
||||
*state_ = state_t::constructed;
|
||||
}
|
||||
|
||||
StateTracker(StateTracker&&) = default;
|
||||
StateTracker(StateTracker const&) = default;
|
||||
|
||||
constexpr StateTracker& operator=(StateTracker&& other) noexcept
|
||||
{
|
||||
*state_ = state_t::inactive;
|
||||
state_ = other.state_;
|
||||
*state_ = state_t::move_assigned;
|
||||
other.state_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr StateTracker& operator=(StateTracker const& other) noexcept
|
||||
{
|
||||
*state_ = state_t::inactive;
|
||||
state_ = other.state_;
|
||||
*state_ = state_t::copy_assigned;
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
state_t* state_;
|
||||
};
|
||||
{
|
||||
auto state = std::array{state_t::inactive, state_t::inactive};
|
||||
auto opt1 = std::optional<StateTracker>(state[0]);
|
||||
assert(state[0] == state_t::constructed);
|
||||
|
||||
auto opt2 = std::optional<StateTracker>(state[1]);
|
||||
assert(state[1] == state_t::constructed);
|
||||
|
||||
opt1 = std::move(opt2);
|
||||
assert(state[0] == state_t::inactive);
|
||||
assert(state[1] == state_t::move_assigned);
|
||||
}
|
||||
{
|
||||
auto state = std::array{state_t::inactive, state_t::inactive};
|
||||
auto opt1 = std::optional<StateTracker>(state[0]);
|
||||
assert(state[0] == state_t::constructed);
|
||||
|
||||
auto opt2 = std::optional<StateTracker>(state[1]);
|
||||
assert(state[1] == state_t::constructed);
|
||||
|
||||
opt1 = opt2;
|
||||
assert(state[0] == state_t::inactive);
|
||||
assert(state[1] == state_t::copy_assigned);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test());
|
||||
#endif
|
||||
test_with_test_type();
|
||||
test_ambiguous_assign();
|
||||
{
|
||||
optional<int> opt;
|
||||
optional<short> opt2;
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt;
|
||||
optional<short> opt2(short{2});
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
optional<short> opt2;
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
}
|
||||
{
|
||||
optional<int> opt(3);
|
||||
optional<short> opt2(short{2});
|
||||
opt = std::move(opt2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||
assert(*opt == *opt2);
|
||||
}
|
||||
test();
|
||||
{
|
||||
optional<std::unique_ptr<B>> opt;
|
||||
optional<std::unique_ptr<D>> other(new D());
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// UNSUPPORTED: gcc-10
|
||||
// <optional>
|
||||
|
||||
// template <class U>
|
||||
|
@ -21,7 +22,7 @@
|
|||
using std::optional;
|
||||
|
||||
template <class T, class U>
|
||||
void
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
test(const optional<U>& rhs, bool is_going_to_throw = false)
|
||||
{
|
||||
bool rhs_engaged = static_cast<bool>(rhs);
|
||||
|
@ -51,17 +52,17 @@ class X
|
|||
{
|
||||
int i_;
|
||||
public:
|
||||
X(int i) : i_(i) {}
|
||||
X(const X& x) : i_(x.i_) {}
|
||||
~X() {i_ = 0;}
|
||||
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
|
||||
constexpr X(int i) : i_(i) {}
|
||||
constexpr X(const X& x) : i_(x.i_) {}
|
||||
TEST_CONSTEXPR_CXX20 ~X() {i_ = 0;}
|
||||
friend constexpr bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
|
||||
};
|
||||
|
||||
class Y
|
||||
{
|
||||
int i_;
|
||||
public:
|
||||
Y(int i) : i_(i) {}
|
||||
constexpr Y(int i) : i_(i) {}
|
||||
|
||||
friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
|
||||
};
|
||||
|
@ -74,48 +75,33 @@ class Z
|
|||
public:
|
||||
Z(int i) : i_(i) {TEST_THROW(6);}
|
||||
|
||||
friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
|
||||
friend bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool test_all()
|
||||
{
|
||||
{
|
||||
optional<U> rhs;
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
optional<U> rhs(U{3});
|
||||
test<T>(rhs);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
typedef short U;
|
||||
typedef int T;
|
||||
optional<U> rhs;
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
typedef short U;
|
||||
typedef int T;
|
||||
optional<U> rhs(U{3});
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
typedef X T;
|
||||
typedef int U;
|
||||
optional<U> rhs;
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
typedef X T;
|
||||
typedef int U;
|
||||
optional<U> rhs(U{3});
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
typedef Y T;
|
||||
typedef int U;
|
||||
optional<U> rhs;
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
typedef Y T;
|
||||
typedef int U;
|
||||
optional<U> rhs(U{3});
|
||||
test<T>(rhs);
|
||||
}
|
||||
test_all<int, short>();
|
||||
test_all<X, int>();
|
||||
test_all<Y, int>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_all<int, short>());
|
||||
static_assert(test_all<X, int>());
|
||||
static_assert(test_all<Y, int>());
|
||||
#endif
|
||||
{
|
||||
typedef Z T;
|
||||
typedef int U;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// UNSUPPORTED: gcc-10
|
||||
// <optional>
|
||||
|
||||
// template <class U>
|
||||
|
@ -21,7 +22,7 @@
|
|||
using std::optional;
|
||||
|
||||
template <class T, class U>
|
||||
void
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
test(const optional<U>& rhs, bool is_going_to_throw = false)
|
||||
{
|
||||
static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value), "");
|
||||
|
@ -52,17 +53,17 @@ class X
|
|||
{
|
||||
int i_;
|
||||
public:
|
||||
explicit X(int i) : i_(i) {}
|
||||
X(const X& x) : i_(x.i_) {}
|
||||
~X() {i_ = 0;}
|
||||
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
|
||||
constexpr explicit X(int i) : i_(i) {}
|
||||
constexpr X(const X& x) : i_(x.i_) {}
|
||||
TEST_CONSTEXPR_CXX20 ~X() {i_ = 0;}
|
||||
friend constexpr bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
|
||||
};
|
||||
|
||||
class Y
|
||||
{
|
||||
int i_;
|
||||
public:
|
||||
explicit Y(int i) : i_(i) {}
|
||||
constexpr explicit Y(int i) : i_(i) {}
|
||||
|
||||
friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
|
||||
};
|
||||
|
@ -73,38 +74,34 @@ class Z
|
|||
{
|
||||
int i_;
|
||||
public:
|
||||
explicit Z(int i) : i_(i) { TEST_THROW(6);}
|
||||
constexpr explicit Z(int i) : i_(i) { TEST_THROW(6);}
|
||||
|
||||
friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool test_all()
|
||||
{
|
||||
{
|
||||
optional<U> rhs;
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
optional<U> rhs(3);
|
||||
test<T>(rhs);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
typedef X T;
|
||||
typedef int U;
|
||||
optional<U> rhs;
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
typedef X T;
|
||||
typedef int U;
|
||||
optional<U> rhs(3);
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
typedef Y T;
|
||||
typedef int U;
|
||||
optional<U> rhs;
|
||||
test<T>(rhs);
|
||||
}
|
||||
{
|
||||
typedef Y T;
|
||||
typedef int U;
|
||||
optional<U> rhs(3);
|
||||
test<T>(rhs);
|
||||
}
|
||||
test_all<X, int>();
|
||||
test_all<Y, int>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_all<X, int>());
|
||||
static_assert(test_all<Y, int>());
|
||||
#endif
|
||||
{
|
||||
typedef Z T;
|
||||
typedef int U;
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
using std::optional;
|
||||
|
||||
template <class T, class U>
|
||||
void
|
||||
test(optional<U>&& rhs, bool is_going_to_throw = false)
|
||||
TEST_CONSTEXPR_CXX20 void test(optional<U>&& rhs, bool is_going_to_throw = false)
|
||||
{
|
||||
static_assert(!(std::is_convertible<optional<U>&&, optional<T>>::value), "");
|
||||
bool rhs_engaged = static_cast<bool>(rhs);
|
||||
|
@ -48,10 +47,10 @@ class X
|
|||
{
|
||||
int i_;
|
||||
public:
|
||||
explicit X(int i) : i_(i) {}
|
||||
X(X&& x) : i_(std::exchange(x.i_, 0)) {}
|
||||
~X() {i_ = 0;}
|
||||
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
|
||||
constexpr explicit X(int i) : i_(i) {}
|
||||
constexpr X(X&& x) : i_(std::exchange(x.i_, 0)) {}
|
||||
TEST_CONSTEXPR_CXX20 ~X() {i_ = 0;}
|
||||
friend constexpr bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
|
||||
};
|
||||
|
||||
int count = 0;
|
||||
|
@ -62,7 +61,7 @@ public:
|
|||
explicit Z(int) { TEST_THROW(6); }
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
TEST_CONSTEXPR_CXX20 bool test()
|
||||
{
|
||||
{
|
||||
optional<int> rhs;
|
||||
|
@ -72,6 +71,16 @@ int main(int, char**)
|
|||
optional<int> rhs(3);
|
||||
test<X>(std::move(rhs));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test());
|
||||
#endif
|
||||
test();
|
||||
{
|
||||
optional<int> rhs;
|
||||
test<Z>(std::move(rhs));
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// REQUIRES: c++17
|
||||
// <optional>
|
||||
|
||||
// constexpr optional(const optional<T>&& rhs);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// UNSUPPORTED: gcc-10
|
||||
// <optional>
|
||||
|
||||
// template <class U>
|
||||
|
@ -22,7 +23,7 @@
|
|||
using std::optional;
|
||||
|
||||
template <class T, class U>
|
||||
void
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
test(optional<U>&& rhs, bool is_going_to_throw = false)
|
||||
{
|
||||
bool rhs_engaged = static_cast<bool>(rhs);
|
||||
|
@ -48,37 +49,39 @@ class X
|
|||
{
|
||||
int i_;
|
||||
public:
|
||||
X(int i) : i_(i) {}
|
||||
X(X&& x) : i_(std::exchange(x.i_, 0)) {}
|
||||
~X() {i_ = 0;}
|
||||
friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
|
||||
TEST_CONSTEXPR_CXX20 X(int i) : i_(i) {}
|
||||
TEST_CONSTEXPR_CXX20 X(X&& x) : i_(std::exchange(x.i_, 0)) {}
|
||||
TEST_CONSTEXPR_CXX20 ~X() {i_ = 0;}
|
||||
friend constexpr bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
|
||||
};
|
||||
|
||||
int count = 0;
|
||||
|
||||
struct Z
|
||||
{
|
||||
Z(int) { TEST_THROW(6); }
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
template<class T, class U>
|
||||
TEST_CONSTEXPR_CXX20 bool test_all()
|
||||
{
|
||||
{
|
||||
optional<short> rhs;
|
||||
test<int>(std::move(rhs));
|
||||
optional<T> rhs;
|
||||
test<U>(std::move(rhs));
|
||||
}
|
||||
{
|
||||
optional<short> rhs(short{3});
|
||||
test<int>(std::move(rhs));
|
||||
}
|
||||
{
|
||||
optional<int> rhs;
|
||||
test<X>(std::move(rhs));
|
||||
}
|
||||
{
|
||||
optional<int> rhs(3);
|
||||
test<X>(std::move(rhs));
|
||||
optional<T> rhs(short{3});
|
||||
test<U>(std::move(rhs));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_all<short, int>();
|
||||
test_all<int, X>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test_all<short, int>());
|
||||
static_assert(test_all<int, X>());
|
||||
#endif
|
||||
{
|
||||
optional<int> rhs;
|
||||
test<Z>(std::move(rhs));
|
||||
|
|
|
@ -40,25 +40,21 @@ int main(int, char**)
|
|||
typedef int T;
|
||||
static_assert(std::is_trivially_destructible<T>::value, "");
|
||||
static_assert(std::is_trivially_destructible<optional<T>>::value, "");
|
||||
static_assert(std::is_literal_type<optional<T>>::value, "");
|
||||
}
|
||||
{
|
||||
typedef double T;
|
||||
static_assert(std::is_trivially_destructible<T>::value, "");
|
||||
static_assert(std::is_trivially_destructible<optional<T>>::value, "");
|
||||
static_assert(std::is_literal_type<optional<T>>::value, "");
|
||||
}
|
||||
{
|
||||
typedef PODType T;
|
||||
static_assert(std::is_trivially_destructible<T>::value, "");
|
||||
static_assert(std::is_trivially_destructible<optional<T>>::value, "");
|
||||
static_assert(std::is_literal_type<optional<T>>::value, "");
|
||||
}
|
||||
{
|
||||
typedef X T;
|
||||
static_assert(!std::is_trivially_destructible<T>::value, "");
|
||||
static_assert(!std::is_trivially_destructible<optional<T>>::value, "");
|
||||
static_assert(!std::is_literal_type<optional<T>>::value, "");
|
||||
{
|
||||
X x;
|
||||
optional<X> opt{x};
|
||||
|
|
|
@ -28,7 +28,7 @@ struct X
|
|||
|
||||
bool X::dtor_called = false;
|
||||
|
||||
int main(int, char**)
|
||||
constexpr bool check_reset()
|
||||
{
|
||||
{
|
||||
optional<int> opt;
|
||||
|
@ -41,6 +41,15 @@ int main(int, char**)
|
|||
opt.reset();
|
||||
assert(static_cast<bool>(opt) == false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
check_reset();
|
||||
#if TEST_STD_VER >= 20
|
||||
static_assert(check_reset());
|
||||
#endif
|
||||
{
|
||||
optional<X> opt;
|
||||
static_assert(noexcept(opt.reset()) == true, "");
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
// UNSUPPORTED: gcc-10
|
||||
// <optional>
|
||||
|
||||
// void swap(optional&)
|
||||
|
@ -63,57 +64,78 @@ public:
|
|||
friend void swap(Z&, Z&) {TEST_THROW(6);}
|
||||
};
|
||||
|
||||
class W
|
||||
{
|
||||
int i_;
|
||||
public:
|
||||
constexpr W(int i) : i_(i) {}
|
||||
|
||||
friend constexpr bool operator==(const W& x, const W& y) {return x.i_ == y.i_;}
|
||||
friend TEST_CONSTEXPR_CXX20 void swap(W& x, W& y) noexcept {std::swap(x.i_, y.i_);}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
TEST_CONSTEXPR_CXX20 bool check_swap()
|
||||
{
|
||||
{
|
||||
optional<T> opt1;
|
||||
optional<T> opt2;
|
||||
static_assert(noexcept(opt1.swap(opt2)) == true);
|
||||
assert(static_cast<bool>(opt1) == false);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
opt1.swap(opt2);
|
||||
assert(static_cast<bool>(opt1) == false);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
}
|
||||
{
|
||||
optional<T> opt1(1);
|
||||
optional<T> opt2;
|
||||
static_assert(noexcept(opt1.swap(opt2)) == true);
|
||||
assert(static_cast<bool>(opt1) == true);
|
||||
assert(*opt1 == 1);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
opt1.swap(opt2);
|
||||
assert(static_cast<bool>(opt1) == false);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 1);
|
||||
}
|
||||
{
|
||||
optional<T> opt1;
|
||||
optional<T> opt2(2);
|
||||
static_assert(noexcept(opt1.swap(opt2)) == true, "");
|
||||
assert(static_cast<bool>(opt1) == false);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
opt1.swap(opt2);
|
||||
assert(static_cast<bool>(opt1) == true);
|
||||
assert(*opt1 == 2);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
}
|
||||
{
|
||||
optional<T> opt1(1);
|
||||
optional<T> opt2(2);
|
||||
static_assert(noexcept(opt1.swap(opt2)) == true, "");
|
||||
assert(static_cast<bool>(opt1) == true);
|
||||
assert(*opt1 == 1);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
opt1.swap(opt2);
|
||||
assert(static_cast<bool>(opt1) == true);
|
||||
assert(*opt1 == 2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
optional<int> opt1;
|
||||
optional<int> opt2;
|
||||
static_assert(noexcept(opt1.swap(opt2)) == true, "");
|
||||
assert(static_cast<bool>(opt1) == false);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
opt1.swap(opt2);
|
||||
assert(static_cast<bool>(opt1) == false);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
}
|
||||
{
|
||||
optional<int> opt1(1);
|
||||
optional<int> opt2;
|
||||
static_assert(noexcept(opt1.swap(opt2)) == true, "");
|
||||
assert(static_cast<bool>(opt1) == true);
|
||||
assert(*opt1 == 1);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
opt1.swap(opt2);
|
||||
assert(static_cast<bool>(opt1) == false);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 1);
|
||||
}
|
||||
{
|
||||
optional<int> opt1;
|
||||
optional<int> opt2(2);
|
||||
static_assert(noexcept(opt1.swap(opt2)) == true, "");
|
||||
assert(static_cast<bool>(opt1) == false);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
opt1.swap(opt2);
|
||||
assert(static_cast<bool>(opt1) == true);
|
||||
assert(*opt1 == 2);
|
||||
assert(static_cast<bool>(opt2) == false);
|
||||
}
|
||||
{
|
||||
optional<int> opt1(1);
|
||||
optional<int> opt2(2);
|
||||
static_assert(noexcept(opt1.swap(opt2)) == true, "");
|
||||
assert(static_cast<bool>(opt1) == true);
|
||||
assert(*opt1 == 1);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 2);
|
||||
opt1.swap(opt2);
|
||||
assert(static_cast<bool>(opt1) == true);
|
||||
assert(*opt1 == 2);
|
||||
assert(static_cast<bool>(opt2) == true);
|
||||
assert(*opt2 == 1);
|
||||
}
|
||||
check_swap<int>();
|
||||
check_swap<W>();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(check_swap<int>());
|
||||
static_assert(check_swap<W>());
|
||||
#endif
|
||||
{
|
||||
optional<X> opt1;
|
||||
optional<X> opt2;
|
||||
|
|
Loading…
Reference in New Issue