std::optional<T>::operator=
optional& operator=( std::nullopt_t ) noexcept;
|
(1) | (C++17 起) (C++20 起 constexpr) |
constexpr optional& operator=( const optional& other );
|
(2) | (C++17 起) |
constexpr optional& operator=( optional&& other ) noexcept(/* see below */);
|
(3) | (C++17 起) |
template< class U = std::remove_cv_t<T> >
optional& operator=( U&& value );
|
(4) | (C++17 起) (C++20 起 constexpr) |
template< class U >
optional& operator=( const optional<U>& other );
|
(5) | (C++17 起) (C++20 起 constexpr) |
template< class U >
optional& operator=( optional<U>&& other );
|
(6) | (C++17 起) (C++20 起 constexpr) |
替换 *this 的内容为 other 的内容。
*this 含有值,则通过调用其析构函数销毁所含值,如同使用 value().T::~T()。在此调用之后 *this 不包含值。other 的状态。
- 若
*this和other都不包含值,则该函数无效果。 - 若
*this包含值,但other不包含,则通过调用其析构函数销毁所含值。在此调用之后*this不包含值。 - 若
other包含值,则根据*this是否包含值,所含值要么被直接初始化,要么从*other(2) 或std::move(*other)(3) 赋值。注意,被移动的 optional 仍然包含值。 - 当 或 是
std::is_copy_constructible_v<T>时,重载std::is_copy_assignable_v<T>(2)false被删除。若std::is_trivially_copy_constructible_v<T>、std::is_trivially_copy_assignable_v<T>和std::is_trivially_destructible_v<T>都是true,则它是平凡。 - 当 或 是
std::is_move_constructible_v<T>时,重载std::is_move_assignable_v<T>(3)false不参与重载决议。若std::is_trivially_move_constructible_v<T>、std::is_trivially_move_assignable_v<T>和std::is_trivially_destructible_v<T>都是true,则它是平凡。
*this 是否包含值,所含值要么从 std::forward<U>(value) 直接初始化,要么从 std::forward<U>(value) 赋值。除非 std::decay_t<U>(C++20 前)std::remove_cvref_t<U>(C++20 起) 不是 std::optional<T>、std::is_constructible_v<T, U> 是 true、std::is_assignable_v<T&, U> 是 true,并且满足以下至少一个条件,否则该函数不参与重载决议:
T不是 标量类型;std::decay_t<U>不是T。
other 的状态。
- 若
*this和other都不包含值,则该函数无效果。 - 若
*this包含值,但other不包含,则通过调用其析构函数销毁所含值。在此调用之后*this不包含值。 - 若
other包含值,则根据*this是否包含值,所含值要么被直接初始化,要么从*other(5) 或std::move(*other)(6) 赋值。注意,被移动的 optional 仍然包含值。 - 这些重载不参与重载决议,除非满足以下条件:
T不能从任何类型为(可能是const)std::optional<U>的表达式构造、转换或赋值,即以下 12 个类型特征均为false:std::is_constructible_v<T, std::optional<U>&>std::is_constructible_v<T, const std::optional<U>&>std::is_constructible_v<T, std::optional<U>&&>std::is_constructible_v<T, const std::optional<U>&&>std::is_convertible_v<std::optional<U>&, T>std::is_convertible_v<const std::optional<U>&, T>std::is_convertible_v<std::optional<U>&&, T>std::is_convertible_v<const std::optional<U>&&, T>std::is_assignable_v<T&, std::optional<U>&>std::is_assignable_v<T&, const std::optional<U>&>std::is_assignable_v<T&, std::optional<U>&&>std::is_assignable_v<T&, const std::optional<U>&&>
- 对于重载 (5),
std::is_constructible_v<T, const U&>和std::is_assignable_v<T&, const U&>都是true。 - 对于重载 (6),
std::is_constructible_v<T, U>和std::is_assignable_v<T&, U>都是true。
参数
| other | - |
另一个
optional
对象,其包含的值将被赋值
|
| value | - | 将要赋值给被包含值的具体数值 |
返回值
* this
异常
T
的构造函数或赋值运算符抛出的任何异常。若抛出异常,则
*
this
(以及对于
(
2-5
)
情况下的
other
)的初始化状态保持不变,即若对象已包含值,则仍包含值,反之亦然。
value
的内容以及
*
this
和
other
所包含的值取决于引发异常的操作(拷贝构造、移动赋值等)的异常安全保证。
std:: is_nothrow_move_constructible_v < T > )
注释
一个可选对象
op
可以通过
op
=
{
}
;
和
op
=
nullopt
;
两种方式转换为空可选对象。第一个表达式使用
{
}
构造一个空的
optional
对象并将其赋值给
op
。
| 特性测试宏 | 值 | 标准 | 特性 |
|---|---|---|---|
__cpp_lib_optional
|
202106L
|
(C++20)
(DR20) |
完全 constexpr ( 1 ) , ( 4-6 ) |
示例
#include <iostream> #include <optional> int main() { std::optional<const char*> s1 = "abc", s2; // 构造函数 s2 = s1; // 赋值操作 s1 = "def"; // 退化赋值 (U = char[4], T = const char*) std::cout << *s2 << ' ' << *s1 << '\n'; }
输出:
abc def
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
| 缺陷报告 | 适用范围 | 发布时行为 | 修正后行为 |
|---|---|---|---|
| LWG 3886 | C++17 |
重载版本
(
6
)
的默认模板参数为
T
|
改为 std:: remove_cv_t < T > |
| P0602R4 | C++17 |
拷贝/移动赋值运算符可能非平凡
即使底层操作是平凡的 |
要求传播平凡性 |
| P2231R1 | C++20 | 重载版本 ( 1,4-6 ) 不是 constexpr | 改为 constexpr |
参见
|
就地构造所含值
(公开成员函数) |