optional
1 _Optional_payload_base
结构体
这个模板管理std::optional
的实际数据。
定义
template <typename _Tp> struct _Optional_payload_base {
using _Stored_type = remove_const_t<_Tp>;
};
有一个存储类型的定义,就是_Tp
去掉const修饰符后的类型。
_Storage
共用体
struct _Empty_byte {
};
template <typename _Up, bool = is_trivially_destructible_v<_Up>>
union _Storage {
constexpr _Storage() noexcept : _M_empty() {
}
template <typename... _Args>
constexpr _Storage(in_place_t, _Args &&...__args)
: _M_value(std::forward<_Args>(__args)...) {
}
template <typename _Vp, typename... _Args>
constexpr _Storage(std::initializer_list<_Vp> __il, _Args &&...__args)
: _M_value(__il, std::forward<_Args>(__args)...) {
}
_Empty_byte _M_empty;
_Up _M_value;
};
template <typename _Up> union _Storage<_Up, false> {
constexpr _Storage() noexcept : _M_empty() {
}
template <typename... _Args>
constexpr _Storage(in_place_t, _Args &&...__args)
: _M_value(std::forward<_Args>(__args)...) {
}
template <typename _Vp, typename... _Args>
constexpr _Storage(std::initializer_list<_Vp> __il, _Args &&...__args)
: _M_value(__il, std::forward<_Args>(__args)...) {
}
// User-provided destructor is needed when _Up has non-trivial dtor.
~_Storage() {
}
_Empty_byte _M_empty;
_Up _M_value;
};
_Storage<_Stored_type> _M_payload;
_Storage
模板的第一个模板参数为_Up
,代表了实际存储的对象的类型。第二个参数为is_trivially_destructible_v<_Up>
。当其为false的时候,有一个特化的版本,里面定义了一个析构函数。一般地,这个共用体的默认构造函数初始化了一个_Empty_byte
对象,是一个空的结构体对象。另外存在两个构造函数,会根据传入的参数初始化一个_up
类型的变量。
_Storage
类型的变量_M_payload
构成了_Optional_payload_base
的核心成员变量,是此结构体的数据实际存储的地方,也是std::optional
的实际存储数据的地方。
另一数据成员:_M_engaged
bool _M_engaged = false;
这个变量表明了这个结构体是否真实承载了数据,也可以理解为_M_payload
为空还是有真实数据的标志。
构造、析构、拷贝、赋值等函数
_Optional_payload_base() = default;
~_Optional_payload_base() = default;
template <typename... _Args>
constexpr _Optional_payload_base(in_place_t __tag, _Args &&...__args)
: _M_payload(__tag, std::forward<_Args>(__args)...), _M_engaged(true) {
}
template <typename _Up, typename... _Args>
constexpr _Optional_payload_base(std::initializer_list<_Up> __il,
_Args &&...__args)
: _M_payload(__il, std::forward<_Args>(__args)...), _M_engaged(true) {
}
// Constructor used by _Optional_base copy constructor when the
// contained value is not trivially copy constructible.
constexpr _Optional_payload_base(bool __engaged,
const _Optional_payload_base &__other) {
if (__other._M_engaged)
this->_M_construct(__other._M_get());
}
// Constructor used by _Optional_base move constructor when the
// contained value is not trivially move constructible.
constexpr _Optional_payload_base(bool __engaged,
_Optional_payload_base &&__other) {
if (__other._M_engaged)
this->_M_construct(std::move(__other._M_get()));
}
// Copy constructor is only used to when the contained value is
// trivially copy constructible.
_Optional_payload_base(const _Optional_payload_base &) = default;
// Move constructor is only used to when the contained value is
// trivially copy constructible.
_Optional_payload_base(_Optional_payload_base &&) = default;
_Optional_payload_base &operator=(const _Optional_payload_base &) = default;
_Optional_payload_base &operator=(_Optional_payload_base &&) = default;
注意参数中有__engaged
参数的拷贝、移动构造函数和不带这个参数的拷贝、移动构造函数的区别。
- 带有这个参数的拷贝、移动构造函数,当other的engaged参数为true时,调用
_M_construct
函数。当包含的具体数据类型不是trivially copy constructible的,_Optional_base
会使用这种函数。 - 不带这个参数的,为默认实现。当包含的具体数据类型是trivially copy constructible的,
_Optional_base
会使用这种函数。
其他成员函数
// used to perform non-trivial copy assignment.
constexpr void _M_copy_assign(const _Optional_payload_base &__other) {
if (this->_M_engaged && __other._M_engaged)
this->_M_get() = __other._M_get();
else {
if (__other._M_engaged)
this->_M_construct(__other._M_get());
else
this->_M_reset();
}
}
// used to perform non-trivial move assignment.
constexpr void _M_move_assign(_Optional_payload_base &&__other) noexcept(
__and_v<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>) {
if (this->_M_engaged && __other._M_engaged)
this->_M_get() = std::move(__other._M_get());
else {
if (__other._M_engaged)
this->_M_construct(std::move(__other._M_get()));
else
this->_M_reset();
}
}
template <typename... _Args>
void _M_construct(_Args &&...__args) noexcept(
is_nothrow_constructible_v<_Stored_type, _Args...>) {
::new ((void *)std::__addressof(this->_M_payload))
_Stored_type(std::forward<_Args>(__args)...);
this->_M_engaged = true;
}
constexpr void _M_destroy() noexcept {
_M_engaged = false;
_M_payload._M_value.~_Stored_type();
}
// The _M_get() operations have _M_engaged as a precondition.
// They exist to access the contained value with the appropriate
// const-qualification, because _M_payload has had the const removed.
constexpr _Tp &_M_get() noexcept {
return this->_M_payload._M_value; }
constexpr const _Tp &_M_get() const noexcept {
return this->_M_payload._M_value;
}
// _M_reset is a 'safe' operation with no precondition.
constexpr void _M_reset() noexcept {
if (this->_M_engaged)
_M_destroy();
}
2 _Optional_payload
结构体
基本定义
// Class template that manages the payload for optionals.
template <typename _Tp,
bool /*_HasTrivialDestructor*/ = is_trivially_destructible_v<_Tp>,
bool /*_HasTrivialCopy */ = is_trivially_copy_assignable_v<_Tp>
&&is_trivially_copy_constructible_v<_Tp>,
bool /*_HasTrivialMove */ = is_trivially_move_assignable_v<_Tp>
&&is_trivially_move_constructible_v<_Tp>>
struct _Optional_payload;
它的模板参数第一个是_Tp
,是实际的数据类型,除此之外,还有三个模板参数:
- 析构是trivial的吗?
- 拷贝构造、赋值是trivial的吗?
- 移动构造、赋值是trivial的吗?
根据这三个的取值不同,有下面几种不同的特化形式:
// Payload for potentially-constexpr optionals (trivial copy/move/destroy).
template <typename _Tp>
struct _Optional_payload<_Tp, true, true, true>
: _Optional_payload_base<_Tp> {
using _Optional_payload_base<_Tp>::_Optional_payload_base;
_Optional_payload() = default;
};
// Payload for optionals with non-trivial copy construction/assignment.
template <typename _Tp>
struct _Optional_payload<_Tp, true, false, true>
: _Optional_payload_base<_Tp> {
using _Optional_payload_base<_Tp>::_Optional_payload_base;
_Optional_payload() = default;
~_Optional_payload() = default;
_Optional_payload(const _Optional_payload &) = default;
_Optional_payload(_Optional_payload &&) = default;
_Optional_payload &operator=(_Optional_payload &&) = default;
// Non-trivial copy assignment.
constexpr _Optional_payload &operator=(const _Optional_payload &__other) {
this->_M_copy_assign(__other);
return *this;
}
};
// Payload for optionals with non-trivial move construction/assignment.
template <typename _Tp>
struct _Optional_payload<_Tp, true, true, false>
: _Optional_payload_base<_Tp> {
using _Optional_payload_base<_Tp>::_Optional_payload_base;
_Optional_payload() = default;
~