std::ranges::views::concat, std::ranges::concat_view

来自cppreference.com
< cpp‎ | ranges
 
 
范围库
范围适配器
 
 
在标头 <ranges> 定义
template< ranges::input_range... Views >

    requires (ranges::view<Views> && ...) && (sizeof...(Views) > 0) &&
              /*concatable*/<Views...>
class concat_view

    : public ranges::view_interface<concat_view<Views...>>
(1) (C++26 起)
namespace views {

    inline constexpr /* 未指定 */ concat = /* 未指定 */;

}
(2) (C++26 起)
调用签名
template< ranges::input_range... Views >
constexpr ranges::view auto ranges::concat_view( Views&&... vs );
(C++26 起)
template< ranges::input_range... Views >
constexpr /* range adaptor closure */ views::concat( Views&&... vs );
(C++26 起)
辅助类型别名
template< class... Rs >

using /*concat-reference-t*/ =

    ranges::common_reference_t<ranges::range_reference_t<Rs>...>;
(3) (仅用于阐述*)
template< class... Rs >
using /*concat-value-t*/ = std::common_type_t<ranges::range_value_t<Rs>...>;
(4) (仅用于阐述*)
template< class... Rs >

using /*concat-rvalue-reference-t*/ =

    ranges::common_reference_t<ranges::range_rvalue_reference_t<Rs>...>;
(5) (仅用于阐述*)
辅助概念
template< class Ref, class RRef, class It >
concept /*concat-indirectly-readable-impl*/ = /* 见描述 */;
(6) (仅用于阐述*)
template< class... Rs >
concept /*concatable*/ = /* 见描述 */;
(7) (仅用于阐述*)
template< bool Const, class... Rs >
concept /*concat-is-random-access*/ = /* 见描述 */;
(8) (仅用于阐述*)
template< bool Const, class... Rs >
concept /*concat-is-bidirectional*/ = /* 见描述 */;
(9) (仅用于阐述*)

concat_view 表现为一个 view 工厂,它接受任意数量的范围和一个实参列表,其所提供的视图开始于首个范围的首个元素并结束于最末范围的最末元素,其间的所有范围元素都按照实参中给出的相应顺序排列,相当于将各实参范围拼接到一起。

1) 此类模板有一个 view 的非空包模板形参,其中每一个都至少实现 input_range 且为 未给出段落名 (7)
2) 名字 views::concat 代表一种范围适配器对象 (RangeAdaptorObject) 。给定子表达式 pq,表达式 views::concat(p, q) 表达式等价ranges::concat_view(p, q)
3) 代表引用类型。需要一项额外约束以保证每个底层范围的 ranges::range_reference_t 都可以转换为 ranges::common_reference_t
4) iterator::value_type,它还额外关注各底层范围的 value_type,以支持底层范围具有代理迭代器的情况。
5) 右值引用,它还正确地支持底层迭代器定制了 iter_move 的情况。
6) 针对 iterator 定义了 indirectly-readable 概念,以使 concat_view 可以实现 input_range。等价于:
template< class... Rs >
concept /*concat-indirectly-readable*/ = // 仅用于阐述
    std::common_reference_with</*concat-reference-t*/<Rs...>&&,
                               /*concat-value-t*/<Rs...>&> &&
    std::common_reference_with</*concat-reference-t*/<Rs...>&&,
                               /*concat-rvalue-reference-t*/<Rs...>&&> &&
    std::common_reference_with</*concat-rvalue-reference-t*/<Rs...>&&,
                               /*concat-value-t*/<Rs...> const&> &&
    (/*concat-indirectly-readable-impl*/</*concat-reference-t*/<Rs...>,
                                         /*concat-rvalue-reference-t*/<Rs...>,
                                         ranges::iterator_t<Rs>> && ...);

其中仅用于阐述的概念 /*concat-indirectly-readable-impl*/

template< class Ref, class RRef, class It >
concept /*concat-indirectly-readable-impl*/ = // 仅用于阐述
    requires(const It it) {
        { *it } -> std::convertible_to<Ref>;
        { ranges::iter_move(it)} -> std::convertible_to<RRef>;
    };
7) 确定任意两个或更多的不同范围是否可以被适配为一个自身实现了范围的序列。等价于:
template< class... Rs >
concept /*concatable*/ = requires { // 仅用于阐述
        typename /*concat-reference-t*/<Rs...>;
        typename /*concat-value-t*/<Rs...>;
        typename /*concat-rvalue-reference-t*/<Rs...>;
    } && /*concat-indirectly-readable*/<Rs...>;
8)Fs 为由 Rs 中除了最末元素之外的所有元素组成的包。等价于:
template<bool Const, class... Rs>
concept /*concat-is-random-access*/ = // 仅用于阐述
    /*all-random-access*/<Const, Rs...> &&
    (common_range</*maybe-const*/<Const, Fs>> && ...);
9)Fs 为由 Rs 中除了最末元素之外的所有元素组成的包。等价于:
template<bool Const, class... Rs>
concept /*concat-is-bidirectional*/ = // 仅用于阐述
    /*all-bidirectional*/<Const, Rs...> &&
    (common_range</*maybe-const*/<Const, Fs>> && ...);

concat_view 总是实现 input_range,且当所适配的每个 view 类型都实现 forward_rangebidirectional_rangerandom_access_rangesized_range 时也实现相应的概念。

当最末底层范围实现 common_rangeconcat_view 可以是 common_range

定制点对象

名字 views::concat 代表一个定制点对象,它是某个字面 semiregular 类类型的 const 函数对象。为阐述目的,以 __concat_fn 表示它的类型的 cv 无限定版本。

__concat_fn 的所有实例均相等。在相同实参上调用 __concat_fn 类型的不同实例的效果是等价的,这与指代该实例的表达式是左值还是右值,以及是否为 const 限定无关(然而不要求 volatile 限定的实例是可调用的)。由此,可以自由地复制 views::concat 并且能彼此替代地使用它的副本。

给定类型集合 Args...,如果 std::declval<Args>()... 满足上面对于 views::concat 的实参的要求,那么 __concat_fn 就实现

否则,__concat_fn 的函数调用运算符不会参与重载决议。

数据成员

成员 描述
std::tuple<Views...> views_ 所有适配的视图对象
(仅用于阐述的成员对象*)

成员函数

构造 concat_view
(公开成员函数)
返回指向起始的迭代器
(公开成员函数)
返回 指向末尾的迭代器或哨位
(公开成员函数)
返回元素数。仅当底层(适配的)范围满足 sized_range 时才提供。
(公开成员函数)
继承自 std::ranges::view_interface
返回视图是否为空。仅当视图满足 forward_range 时提供。
(std::ranges::view_interface<D> 的公开成员函数)
(C++23)
返回指向范围起始的常量迭代器。
(std::ranges::view_interface<D> 的公开成员函数)
(C++23)
返回对应于范围常量迭代器的哨位。
(std::ranges::view_interface<D> 的公开成员函数)
返回派生视图是否为非空。仅当 ranges::empty 可应用于它时提供。
(std::ranges::view_interface<D> 的公开成员函数)
返回派生视图中的首元素。仅当视图满足 forward_range 时提供。
(std::ranges::view_interface<D> 的公开成员函数)
返回派生视图中的末元素。仅当视图满足 bidirectional_rangecommon_range 时提供。
(std::ranges::view_interface<D> 的公开成员函数)
返回派生视图中的第 n 个元素。仅当视图满足 random_access_range 时提供。
(std::ranges::view_interface<D> 的公开成员函数)

推导指引

嵌套类

类名 定义
迭代器类型
(仅用于阐述的成员类模板*)

辅助模板

没有针对 concat_viewranges::enable_borrowed_range 特化,因为它要求它的迭代器的实现中从始至终包含所有底层范围的所有迭代器和哨位的副本。

注解

没有实参的 views::concat() 是非良构的,因为不存在确定一种元素类型 T 的合理方法。单个实参的 views::concat(r) 表达式等价于 views::all(r)

功能特性测试 标准 功能特性
__cpp_lib_ranges_concat 202403L (C++26) std::ranges::concat_view

示例

初步版本可以在 Compiler Explorer 上测试。

#include <cassert>
#include <list>
#include <print>
#include <ranges>
#include <vector>
 
int main()
{
    std::vector<int> v0{1, 2, 3}, v1{4, 5};
    int a[]{6, 7};
    int i{8};
    auto ie{std::views::single(i)};
 
    auto con = std::views::concat(v0, v1, a, ie);
    assert(con.size() == v0.size() + v1.size() + std::size(a) + ie.size());
    std::println("con.size():{}", con.size());
    std::println("con:{}", con);
    con[6] = 42; // con 是 random_access_range, operator[] 返回引用
    assert(a[1] == 42); // 经由 con[6] 改动 a[1]
    std::println("con:{}", con);
 
    std::list<int> l{7, 8}; // list 是双向范围
    auto cat = std::views::concat(v0, l);
    std::println("cat:{}", cat);
    // cat[0] = 13; // 编译时错误:cat 是双向的 => 没有 operator[]
}

输出:

con.size():8
con:[1, 2, 3, 4, 5, 6, 7, 8]
con:[1, 2, 3, 4, 5, 6, 42, 8]
cat:[1, 2, 3, 7, 8]

引用

  • C++26 标准(ISO/IEC 14882:2026):
  • 26.7.18 Concat view [range.concat]

参阅

由拉平 range 组成的 view 所获得的序列构成的 view
(类模板) (范围适配器对象)
由拉平范围组成的视图并以分隔符间隔所获得的序列构成的 view
(类模板) (范围适配器对象)
到被适配视图的对应元素的引用元组组成的 view
(类模板) (定制点对象)
计算各适配视图的 n 元笛卡尔积所得的元组组成的 view
(类模板) (定制点对象)