命名空间
变体
操作

可分配包装器 (C++20)

来自 cppreference.com
< cpp‎ | ranges
 
 
范围库
范围适配器
辅助项
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 起) 和存储可调用对象的范围适配器在说明性类模板 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(/* see below */);
(自 C++20 起)
(直到 C++23)
constexpr /*movable-box*/& operator=(const /*movable-box*/& other);
    noexcept(/* see below */) 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> 的公共成员函数) [edit]
销毁包含的值(如果有)
(std::optional<T> 的公共成员函数) [edit]
赋值内容
(std::optional<T> 的公共成员函数) [edit]
观察者
访问包含的值
(std::optional<T> 的公共成员函数) [edit]
检查对象是否包含值
(std::optional<T> 的公共成员函数) [edit]
修改器
销毁任何包含的值
(std::optional<T> 的公共成员函数) [edit]
在原位构造包含的值
(std::optional<T> 的公共成员函数) [edit]

[edit] 注释

只有在以下情况下,copyable-box(直到 C++23)movable-box(自 C++23) 才会不包含值:

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

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

功能测试 Std 功能
__cpp_lib_ranges 201911L (C++20) 范围库受限算法
202106L (C++20)
(DR)
默认可初始化视图
202207L (C++23) 放宽 范围适配器 以允许移动类型

[edit] 缺陷报告

以下行为更改缺陷报告被追溯应用到先前发布的 C++ 标准。

DR 应用于 已发布的行为 正确行为
P2325R3 C++20 如果 T 不是 default_initializable,默认构造函数
构造一个不包含值的包装器
包装器也是
不是 default_initializable
LWG 3572 C++20 条件不同的赋值运算符不是 constexpr 变为 constexpr

[edit] 另请参阅

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