命名空间
变体
操作

可赋值包装器 (C++20)

来自 cppreference.cn
< cpp‎ | ranges
 
 
范围库 (Ranges library)
范围适配器 (Range adaptors)
辅助项 (Helper items)
copyable-box
movable-box
(直到 C++23)  (C++23)


 
template< class T >

    requires std::copy_constructible<T> && std::is_object_v<T>

class /*copyable-box*/;
(C++20 起)
(直至 C++23)
(仅作说明*)
template< class T >

    requires std::move_constructible<T> && std::is_object_v<T>

class /*movable-box*/;
(C++23 起)
(仅作说明*)

ranges::single_view, ranges::repeat_view,(C++23 起) 以及存储可调用对象的 Range Adaptor 都通过一个仅用于说明的类模板 copyable-box(C++23 前)movable-box(C++23 起) 进行指定。此处显示的名称仅用于说明目的。

该包装器的行为与 std::optional<T> 完全相同,但默认构造函数、复制赋值运算符和移动赋值运算符与 std::optional 的(有条件地)不同,这在需要时为 T 增加了可赋值性,并使其始终满足 copyablemovable(C++23 起)

如果 T 已经 copyable,或者 std::is_nothrow_move_constructible_v<T>std::is_nothrow_copy_constructible_v<T> 都为 true,则 /*copyable-box*/<T> 可能只存储一个 T 对象,因为它总是包含一个值。

(直至 C++23)

如果 T

/*movable-box*/<T> 可能只存储一个 T 对象,因为它总是包含一个值。

(C++23 起)

目录

[编辑] 模板参数

T - 所包含值的类型,必须是建模 copy_constructible(C++23 前)move_constructible(C++23 起) 的对象类型

[编辑] 成员函数

默认构造函数

constexpr /*copyable-box*/() noexcept(std::is_nothrow_default_constructible_v<T>)

    requires std::default_initializable<T>

    : /*copyable-box*/(std::in_place) { }
(C++20 起)
(直至 C++23)
constexpr /*movable-box*/() noexcept(std::is_nothrow_default_constructible_v<T>)

    requires std::default_initializable<T>

    : /*movable-box*/(std::in_place) { }
(C++23 起)

仅当 T 建模 default_initializable 时才提供默认构造函数。

默认构造的包装器包含一个值初始化的 T 对象。

赋值运算符

(1)
constexpr /*copyable-box*/& operator=(const /*copyable-box*/& other);
    noexcept(/* 参见下文 */);
(C++20 起)
(直至 C++23)
constexpr /*movable-box*/& operator=(const /*movable-box*/& other);
    noexcept(/* 参见下文 */) requires std::copy_constructible<T>;
(C++23 起)
(2)
constexpr /*copyable-box*/& operator=(/*copyable-box*/&& other)
    noexcept(std::is_nothrow_move_constructible_v<T>);
(C++20 起)
(直至 C++23)
constexpr /*movable-box*/& operator=(/*movable-box*/&& other)
    noexcept(std::is_nothrow_move_constructible_v<T>);
(C++23 起)
1) 如果不建模 std::copyable<T>,则复制赋值运算符等价地定义为

constexpr /*copyable-box*/& operator=(const /*copyable-box*/& other)
    noexcept(std::is_nothrow_copy_constructible_v<T>)
{
    if (this != std::addressof(other))
        if (other)
            emplace(*other);
        else
            reset();

    return *this;
}

(直至 C++23)

constexpr /*movable-box*/& operator=(const /*movable-box*/& other)
    noexcept(std::is_nothrow_copy_constructible_v<T>)
    requires std::copy_constructible<T>
{
    if (this != std::addressof(other))
        if (other)
            emplace(*other);
        else
            reset();

    return *this;
}

(C++23 起)
否则,它与 std::optional 的复制赋值运算符相同。
2) 如果不建模 std::movable<T>,则移动赋值运算符等价地定义为

constexpr /*copyable-box*/& operator=(/*copyable-box*/&& other)
    noexcept(std::is_nothrow_move_constructible_v<T>)
{
    if (this != std::addressof(other))
        if (other)
            emplace(std::move(*other));
        else
            reset();

    return *this;
}

(直至 C++23)

constexpr /*movable-box*/& operator=(/*movable-box*/&& other)
    noexcept(std::is_nothrow_move_constructible_v<T>)
{
    if (this != std::addressof(other))
        if (other)
            emplace(std::move(*other));
        else
            reset();

    return *this;
}

(C++23 起)
否则,它与 std::optional 的移动赋值运算符相同。

std::optional 相同的成员

成员函数

构造 optional 对象
(std::optional<T> 的公共成员函数) [编辑]
如果存在,销毁所包含的值
(std::optional<T> 的公共成员函数) [编辑]
赋值内容
(std::optional<T> 的公共成员函数) [编辑]
观察器
访问所包含的值
(std::optional<T> 的公共成员函数) [编辑]
检查对象是否包含值
(std::optional<T> 的公共成员函数) [编辑]
修改器
销毁任何包含的值
(std::optional<T> 的公共成员函数) [编辑]
就地构造包含的值
(std::optional<T> 的公共成员函数) [编辑]

[编辑] 注意

一个 copyable-box(C++23 前)movable-box(C++23 起) 仅在以下情况下不包含值:

  • T 不建模 movablecopyable,并且在移动赋值或复制赋值时分别抛出异常,或
  • 它从另一个无值包装器初始化/赋值。

P2325R3 之前,该包装器在标准中称为 semiregular-box,并且始终满足 semiregular,因为总是提供默认构造函数(这可能会构造一个无值包装器)。

特性测试 标准 特性
__cpp_lib_ranges 201911L (C++20) Ranges 库受限算法
202106L (C++20)
(DR)
不可默认初始化视图
202207L (C++23) 放宽 Range Adaptor 以允许仅移动类型

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
P2325R3 C++20 如果 T 不是 default_initializable,则默认构造函数
构造一个不包含值的包装器
该包装器也
不可default_initializable
LWG 3572 C++20 有条件的赋值运算符不是 constexpr 已改为 constexpr

[编辑] 参见

一个包含单个指定值的 view
(类模板) (定制点对象)[编辑]
一个由重复生成相同值组成的view
(类模板) (定制点对象)[编辑]
一个 view,由满足谓词的 range 的元素组成
(类模板) (范围适配器对象)[编辑]
一个将转换函数应用于每个元素的序列 view
(类模板) (范围适配器对象)[编辑]
一个 view,包含另一个 view 的初始元素,直到谓词对第一个元素返回 false
(类模板) (范围适配器对象)[编辑]
一个 view,包含另一个 view 的元素,跳过初始元素子序列,直到谓词对第一个元素返回 false
(类模板) (范围适配器对象)[编辑]
一个由转换函数应用于适配视图中对应元素的结果组成的 view
(类模板) (定制点对象)[编辑]
一个 view,由对适配视图的相邻元素应用转换函数的结果组成
(类模板) (范围适配器对象)[编辑]