{ }
#endif
+#if __cpp_concepts >= 202002L // Conditionally trivial special member functions
+ ~_Storage() = default;
+
+ // User-provided destructor is needed when _Up has non-trivial dtor.
+ _GLIBCXX20_CONSTEXPR
+ ~_Storage() requires (!is_trivially_destructible_v<_Up>)
+ { }
+
+ _Storage(const _Storage&) = default;
+ _Storage(_Storage&&) = default;
+ _Storage& operator=(const _Storage&) = default;
+ _Storage& operator=(_Storage&&) = default;
+#endif
+
_Empty_byte _M_empty;
_Up _M_value;
};
+#if __cpp_concepts < 202002L
template<typename _Up>
union _Storage<_Up, false>
{
// User-provided destructor is needed when _Up has non-trivial dtor.
_GLIBCXX20_CONSTEXPR ~_Storage() { }
+ _Storage(const _Storage&) = default;
+ _Storage(_Storage&&) = default;
+ _Storage& operator=(const _Storage&) = default;
+ _Storage& operator=(_Storage&&) = default;
+
_Empty_byte _M_empty;
_Up _M_value;
};
+#endif
_Storage<_Stored_type> _M_payload;
_GLIBCXX20_CONSTEXPR ~_Optional_payload() { this->_M_reset(); }
};
- // Common base class for _Optional_base<T> to avoid repeating these
- // member functions in each specialization.
- template<typename _Tp, typename _Dp>
- class _Optional_base_impl
- {
- protected:
- using _Stored_type = remove_const_t<_Tp>;
-
- // The _M_construct operation has !_M_engaged as a precondition
- // while _M_destruct has _M_engaged as a precondition.
- template<typename... _Args>
- constexpr void
- _M_construct(_Args&&... __args)
- noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
- {
- static_cast<_Dp*>(this)->_M_payload._M_construct(
- std::forward<_Args>(__args)...);
- }
-
- constexpr void
- _M_destruct() noexcept
- { static_cast<_Dp*>(this)->_M_payload._M_destroy(); }
-
- // _M_reset is a 'safe' operation with no precondition.
- constexpr void
- _M_reset() noexcept
- { static_cast<_Dp*>(this)->_M_payload._M_reset(); }
-
- constexpr bool _M_is_engaged() const noexcept
- { return static_cast<const _Dp*>(this)->_M_payload._M_engaged; }
-
- // The _M_get operations have _M_engaged as a precondition.
- constexpr _Tp&
- _M_get() noexcept
- { return static_cast<_Dp*>(this)->_M_payload._M_get(); }
-
- constexpr const _Tp&
- _M_get() const noexcept
- { return static_cast<const _Dp*>(this)->_M_payload._M_get(); }
- };
-
/**
* @brief Class template that provides copy/move constructors of optional.
*
bool = is_trivially_copy_constructible_v<_Tp>,
bool = is_trivially_move_constructible_v<_Tp>>
struct _Optional_base
- : _Optional_base_impl<_Tp, _Optional_base<_Tp>>
{
// Constructors for disengaged optionals.
constexpr _Optional_base() = default;
// Copy and move constructors.
constexpr
_Optional_base(const _Optional_base& __other)
+ noexcept(is_nothrow_copy_constructible_v<_Tp>)
: _M_payload(__other._M_payload._M_engaged, __other._M_payload)
{ }
std::move(__other._M_payload))
{ }
+#if __cpp_concepts >= 202002L // Conditionally trivial special member functions
+ // Define these in the primary template if possible, so that we don't
+ // need to use partial specializations of this class template.
+ constexpr _Optional_base(const _Optional_base&)
+ requires is_trivially_copy_constructible_v<_Tp> = default;
+
+ constexpr _Optional_base(_Optional_base&&)
+ requires is_trivially_move_constructible_v<_Tp> = default;
+#endif
+
// Assignment operators.
_Optional_base& operator=(const _Optional_base&) = default;
_Optional_base& operator=(_Optional_base&&) = default;
_Optional_payload<_Tp> _M_payload;
+
+ protected:
+ // For the primary template, we define these functions here.
+ using _Stored_type = remove_const_t<_Tp>;
+
+ // The _M_construct operation has !_M_engaged as a precondition
+ // while _M_destruct has _M_engaged as a precondition.
+ template<typename... _Args>
+ constexpr void
+ _M_construct(_Args&&... __args)
+ noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
+ {
+ _M_payload._M_construct(std::forward<_Args>(__args)...);
+ }
+
+ constexpr void
+ _M_destruct() noexcept
+ { _M_payload._M_destroy(); }
+
+ // _M_reset is a 'safe' operation with no precondition.
+ constexpr void
+ _M_reset() noexcept
+ { _M_payload._M_reset(); }
+
+ constexpr bool _M_is_engaged() const noexcept
+ { return _M_payload._M_engaged; }
+
+ // The _M_get operations have _M_engaged as a precondition.
+ constexpr _Tp&
+ _M_get() noexcept
+ { return _M_payload._M_get(); }
+
+ constexpr const _Tp&
+ _M_get() const noexcept
+ { return _M_payload._M_get(); }
+ };
+
+#if __cpp_concepts < 202002L
+ // If P0848R3 "Conditionally Trivial Special Member Functions" is not
+ // supported (as determined from the __cpp_concepts macro value), the
+ // _Optional_base primary template only has non-trivial copy and move
+ // constructors. Use partial specializations of _Optional_base<T, C, M>
+ // that have a trivial copy and/or move constructor.
+
+ // Common base class for _Optional_base<T> to avoid repeating these
+ // member functions in each partial specialization.
+ // Only used if P0848R3 "Conditionally Trivial Special Member Functions"
+ // is not supported, as indicated by the __cpp_concepts value.
+ template<typename _Tp, typename _Dp>
+ class _Optional_base_impl
+ {
+ protected:
+ using _Stored_type = remove_const_t<_Tp>;
+
+ // The _M_construct operation has !_M_engaged as a precondition
+ // while _M_destruct has _M_engaged as a precondition.
+ template<typename... _Args>
+ constexpr void
+ _M_construct(_Args&&... __args)
+ noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
+ {
+ static_cast<_Dp*>(this)->_M_payload._M_construct(
+ std::forward<_Args>(__args)...);
+ }
+
+ constexpr void
+ _M_destruct() noexcept
+ { static_cast<_Dp*>(this)->_M_payload._M_destroy(); }
+
+ // _M_reset is a 'safe' operation with no precondition.
+ constexpr void
+ _M_reset() noexcept
+ { static_cast<_Dp*>(this)->_M_payload._M_reset(); }
+
+ constexpr bool _M_is_engaged() const noexcept
+ { return static_cast<const _Dp*>(this)->_M_payload._M_engaged; }
+
+ // The _M_get operations have _M_engaged as a precondition.
+ constexpr _Tp&
+ _M_get() noexcept
+ { return static_cast<_Dp*>(this)->_M_payload._M_get(); }
+
+ constexpr const _Tp&
+ _M_get() const noexcept
+ { return static_cast<const _Dp*>(this)->_M_payload._M_get(); }
};
template<typename _Tp>
- struct _Optional_base<_Tp, false, true>
+ struct _Optional_base<_Tp, false, true> // trivial move ctor
: _Optional_base_impl<_Tp, _Optional_base<_Tp>>
{
// Constructors for disengaged optionals.
};
template<typename _Tp>
- struct _Optional_base<_Tp, true, false>
+ struct _Optional_base<_Tp, true, false> // trivial copy ctor
: _Optional_base_impl<_Tp, _Optional_base<_Tp>>
{
// Constructors for disengaged optionals.
};
template<typename _Tp>
- struct _Optional_base<_Tp, true, true>
+ struct _Optional_base<_Tp, true, true> // trivial copy and move ctors
: _Optional_base_impl<_Tp, _Optional_base<_Tp>>
{
// Constructors for disengaged optionals.
_Optional_payload<_Tp> _M_payload;
};
+#endif // __cpp_concepts
template<typename _Tp>
class optional;