Namespaces
Variants

std::ranges::subrange

来自 zh.cppreference.net
 
 
范围库
范围适配器
 
 
定义于头文件 <ranges>
template<
    std::input_or_output_iterator I,
    std::sentinel_for<I> S = I,
    ranges::subrange_kind K = std::sized_sentinel_for<S, I> ?
                                  ranges::subrange_kind::sized :
                                  ranges::subrange_kind::unsized >
    requires (K == ranges::subrange_kind::sized || !std::sized_sentinel_for<S, I>)
class subrange
    : public ranges::view_interface<subrange<I, S, K>>
(1) (C++20 起)
辅助概念
template<class From, class To>
concept /*uses-nonqualification-pointer-conversion*/ =
    /* see description */;
(2) (仅用于阐述*)
template<class From, class To>
concept /*convertible-to-non-slicing*/ = /* see description */;
(3) (仅用于阐述*)
1) 类模板 subrange 将迭代器和哨位组合成单个 view。它符合 sized_range 当且仅当最后一个模板参数是 subrange_kind​::​sized 时(当 std::sized_sentinel_for<S, I> 满足,或 size 作为构造函数参数显式传递时发生)。
2) 确定 From 是否可以在不发生To资质转换的情况下转换为 。等价于:
template<class From, class To>
concept /*uses-nonqualification-pointer-conversion*/ =
    std::is_pointer_v<From> && std::is_pointer_v<To> &&
        !std::convertible_to<std::remove_pointer_t<From>(*)[],
                             std::remove_pointer_t<To>(*)[]>;
3) 确定 From 是否可以在不发生派生到基类转换的情况下转换为 To:
template<class From, class To>
concept /*convertible-to-non-slicing*/ =
    std::convertible_to<From, To> &&
        !/*uses-nonqualification-pointer-conversion*/
            <std::decay_t<From>, std::decay_t<To>>;

数据成员

成员 描述
constexpr bool StoreSize [静态] K == ranges::subrange_kind::sized &&
    !std::sized_sentinel_for<S, I>

(仅为说明的静态成员常量*)
I begin_ 指向子范围起始的迭代器
(仅为说明的成员对象*)
S end_ 表示子范围末尾的哨位
(仅为说明的成员对象*)
make-unsigned-like-t <std::iter_difference_t<I>> size_
(仅在 StoreSize 为 true 时存在)
子范围的大小
(仅为说明的成员对象*)

成员函数

创建新的 subrange
(公开成员函数)
将 subrange 转换为 pair-like 类型
(公开成员函数)
观察器
获取迭代器
(公开成员函数)
获取哨兵
(公开成员函数)
检查 subrange 是否为空
(公开成员函数)
获取 subrange 的大小
(公开成员函数)
迭代器操作
按给定距离推进迭代器
(公开成员函数)
获取 subrange 的副本,其迭代器按给定距离递减
(公开成员函数)
获取 subrange 的副本,其迭代器按给定距离推进
(公开成员函数)
继承自 ranges::view_interface
(C++23)
返回指向范围起始的常量迭代器
(std::ranges::view_interface<D> 的公开成员函数)
(C++23)
返回范围常量迭代器的哨位
(std::ranges::view_interface<D> 的公开成员函数)
返回所派生视图是否非空,仅在 ranges::empty 可应用于该视图时提供
(std::ranges::view_interface<D> 的公开成员函数)
获取派生视图数据的地址,仅在其迭代器类型满足 contiguous_iterator
时提供 std::ranges::view_interface<D>(公开成员函数)
返回派生视图中的首个元素,在其满足 forward_range
时提供 std::ranges::view_interface<D>(公开成员函数)
返回派生视图中的最后一个元素,仅在其满足 bidirectional_range 和 common_range
时提供 std::ranges::view_interface<D>(公开成员函数)
返回派生视图中的第 nth 个元素,仅在其满足 random_access_range
时提供 std::ranges::view_interface<D>(公开成员函数)

推导指引

非成员函数

从 std::ranges::subrange 获取迭代器或哨兵
(函数模板)

辅助类型

指定 std::ranges::subrange 是否建模 std::ranges::sized_range
(枚举)
获取 std::ranges::subrange 的大小
(类模板特化)
获取 std::ranges::subrange 的迭代器或哨兵类型
(类模板特化)

辅助模板

template < class I, class S, ranges:: subrange_kind K >
constexpr bool ranges:: enable_borrowed_range < ranges :: subrange < I, S, K >> = true ;
(C++20 起)

此 ranges:: enable_borrowed_range 的特化使 subrange 满足 borrowed_range 的要求。

示例

#include <map>
#include <print>
#include <ranges>
void make_uppercase(char& v)
{
    v += 'A' - 'a';
}
void uppercase_transform(std::multimap<int, char>& m, int k)
{
    auto [first, last] = m.equal_range(k);
    for (auto& [_, v] : std::ranges::subrange(first, last))
        make_uppercase(v);
}
int main()
{
    std::multimap<int, char> mm{{4, 'a'}, {3, '-'}, {4, 'b'}, {5, '-'}, {4, 'c'}};
    std::println("Before: {}", mm);
    uppercase_transform(mm, 4);
    std::println("After:  {}", mm);
}

输出:

Before: {3: '-', 4: 'a', 4: 'b', 4: 'c', 5: '-'}
After:  {3: '-', 4: 'A', 4: 'B', 4: 'C', 5: '-'}

缺陷报告

下列行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。

DR 适用范围 发布时的行为 正确行为
LWG 3470 C++20 convertible-to-non-slicing 可能拒绝限定转换 始终接受限定转换

参见

用于定义 view 的辅助类模板,采用 奇异递归模板模式
(类模板)

外部链接

在C++20中读写给定键对应的所有 std::multimap 值 — Stack Overflow