为何std::expected<T,E>要求可拷贝赋值的T必须可拷贝构造?
为什么
std::expected<T, int>不可拷贝赋值,即便T可拷贝赋值? 你的T类型禁用了拷贝构造但保留了拷贝赋值,所以单独看T,std::is_copy_assignable_v<T>为true是合理的——毕竟已经存在的T对象之间能正常赋值。但std::expected<T, E>的拷贝赋值逻辑要复杂得多,核心原因在于它要处理两种状态之间的转换:
关键:std::expected的赋值必须覆盖所有状态组合
std::expected要么存着一个T类型的有效值,要么存着一个E类型的错误值。拷贝赋值得处理下面四种情况:
- 源和目标都存有效值:直接对
T做拷贝赋值,这步你的T能搞定。 - 源和目标都存错误值:直接对
E做拷贝赋值,这里int完全没问题。 - 源存有效值,目标存错误值:这时候目标得先销毁当前的错误值,然后用源的
T拷贝构造一个新的T对象(因为目标之前根本没有T的实例)。但你的T禁用了拷贝构造,这一步直接卡壳,整个赋值操作没法完成。 - 源存错误值,目标存有效值:目标销毁当前的
T,然后拷贝构造E的错误值,这步int也没问题。
正是第三种场景的存在,要求T必须同时支持拷贝构造和拷贝赋值——否则当目标处于错误状态时,没法从源的有效值构造出自己的T成员,标准自然不会让std::expected<T,E>的拷贝赋值生效。
移动赋值的情况完全同理
如果T可移动赋值但不可移动构造,当目标是错误状态、源是右值的有效值时,目标需要移动构造T对象,这一步会因为T不可移动构造而失败。所以std::expected的移动赋值也要求T同时支持移动构造和移动赋值。
内容的提问来源于stack exchange,提问作者Voko
相关产品推荐
相关产品推荐

