Section hub

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

concat_view presents a view factory that takes an arbitrary number of ranges as an argument list, and provides a view that starts at the first element of the first range, ends at the last element of the last range, with all range elements sequenced in between respectively in the order given in the arguments, effectively concatenating, or chaining together the argument ranges.

# Declarations

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

(since C++26)

namespace views {
inline constexpr /* unspecified */ concat = /* unspecified */;
}

(since C++26)

Call signature
template< ranges::viewable_range... Rs >
requires /* see below */
constexpr ranges::view auto concat( Rs&&... rs );

(since C++26)

Helper type aliases
template< class... Rs >
using /*concat-reference-t*/ =
ranges::common_reference_t<ranges::range_reference_t<Rs>...>;

(exposition only*)

template< class... Rs >
using /*concat-value-t*/ = std::common_type_t<ranges::range_value_t<Rs>...>;

(exposition only*)

template< class... Rs >
using /*concat-rvalue-reference-t*/ =
ranges::common_reference_t<ranges::range_rvalue_reference_t<Rs>...>;

(exposition only*)

Helper concepts
template< class Ref, class RRef, class It >
concept /*concat-indirectly-readable-impl*/ = /* see description */;

(exposition only*)

template< class... Rs >
concept /*concatable*/ = /* see description */;

(exposition only*)

# Notes

No argument views::concat() is ill-formed, because there is no reasonable way to determine an element type T. Single argument views::concat(r) is expression equivalent to views::all(r).

# Example

#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 is random_access_range, operator[] returns a reference
    assert(a[1] == 42); // a[1] was modified via con[6]
    std::println("con: {}", con);
 
    std::list<int> l{7, 8}; // list is bidirectional range
    auto cat = std::views::concat(v0, l);
    std::println("cat: {}", cat);
    // cat[0] = 13; // compile-time error: cat is bidirectional => no operator[]
}

# See also

This hub groups the ranges library by user task rather than by raw reference tree shape. View types and adaptor objects are presented as the same conceptual item.

Core adapters

Start here for the adapters most people reach for first when building pipelines.

Utility views

These adapt shape, ownership, or projection rather than representing the “headline” pipeline steps.

New in C++23 / C++26

Newer adapters, kept as a compact scan list with only standard badges.

All entities by category

A lighter-weight index of the full ranges surface, grouped by conceptual task instead of raw page-tree names.

74 entities