[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
NOKEYCHECK=True
GitOrigin-RevId: 546449938a39dcc65f60f8d6e44e7b058a026549
diff --git a/include/optional b/include/optional
index b6a464f..8a291a6 100644
--- a/include/optional
+++ b/include/optional
@@ -69,7 +69,7 @@
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 @@
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 @@
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 @@
bool __engaged_;
_LIBCPP_INLINE_VISIBILITY
- ~__optional_destruct_base()
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
{
if (__engaged_)
__val_.~value_type();
@@ -239,7 +239,7 @@
__engaged_(true) {}
_LIBCPP_INLINE_VISIBILITY
- void reset() noexcept
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
{
if (__engaged_)
{
@@ -274,7 +274,7 @@
__engaged_(true) {}
_LIBCPP_INLINE_VISIBILITY
- void reset() noexcept
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
{
if (__engaged_)
{
@@ -319,16 +319,20 @@
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 @@
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 @@
}
_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 @@
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 @@
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 @@
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 @@
__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 @@
__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 @@
__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 @@
__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 @@
_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 @@
_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 @@
_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 @@
_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 @@
>::value>
>
_LIBCPP_INLINE_VISIBILITY
- optional&
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
operator=(_Up&& __v)
{
if (this->has_value())
@@ -798,7 +802,7 @@
_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 @@
_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 @@
>
>
_LIBCPP_INLINE_VISIBILITY
- _Tp &
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
emplace(_Args&&... __args)
{
reset();
@@ -839,7 +843,7 @@
>
>
_LIBCPP_INLINE_VISIBILITY
- _Tp &
+ _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
emplace(initializer_list<_Up> __il, _Args&&... __args)
{
reset();
@@ -848,7 +852,7 @@
}
_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 @@
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 @@
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