std::ranges...product_view(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

🌸 NAME 🌸

std::ranges::views::cartesian_product, std::ranges::cartesian_product_view β€” okay bestie, this is the whole name, no cap πŸ’…

This page is std::ranges...product_view(3) from the C++ Standard Libary manual, and we are about to make the cartesian product make sense. ✨


✨ Synopsis ✨

Defined in header <ranges> 🫢

template< ranges::input_range First, ranges::forward_range... Vs >
    requires (ranges::view<First> && ... && ranges::view<Vs>)     (1)
(since C++23)
class cartesian_product_view
    : public ranges::view_interface<cartesian_product_view<First, Vs...>>
namespace views {
    inline constexpr /*unspecified*/ cartesian_product =          (2)
(since C++23)
    /*unspecified*/;
}

Call signature

template< ranges::viewable_range... Rs >
    requires /* see below */
(since C++23)
constexpr auto cartesian_product( Rs&&... rs );

Helper concepts

template< bool Const, class First, class... Vs >
concept __cartesian_product_is_random_access =
    (ranges::random_access_range<__maybe_const<Const, First>> &&  (3)
(exposition
    ... &&
only*)
        (ranges::random_access_range<__maybe_const<Const, Vs>> &&
            ranges::sized_range<__maybe_const<Const, Vs>>));

template< class R >
concept __cartesian_product_common_arg =
(exposition
    ranges::common_range<R> ||                                    (4)
only*)
        (ranges::sized_range<R> &&
ranges::random_access_range<R>);

template< bool Const, class First, class... Vs >
concept __cartesian_product_is_bidirectional =
    (ranges::bidirectional_range<__maybe_const<Const, First>> &&
(exposition
    ... &&                                                            (5)
only*)
        (ranges::bidirectional_range<__maybe_const<Const, Vs>> &&
            __cartesian_product_common_arg<__maybe_const<Const, Vs>>));

template< class First, class... Vs >
                                                                                (exposition
concept __cartesian_product_is_common =                           (6)
only*)
    __cartesian_product_common_arg<First>;

template< class... Vs >
                                                                                (exposition
concept __cartesian_product_is_sized =                            (7)
only*)
    (ranges::sized_range<Vs> && ...);

template< bool Const, template<class> class FirstSent, class First, class... Vs >
concept __cartesian_is_sized_sentinel =
    (ranges::sized_sentinel_for<FirstSent<__maybe_const<Const, First>>,
            ranges::iterator_t<__maybe_const<Const, First>>> && ...   (8)
(exposition
    &&
only*)
        (ranges::sized_range<__maybe_const<Const, Vs>> &&
    ranges::sized_sentinel_for<iterator_t<__maybe_const<Const, Vs>>,
                        ranges::iterator_t<__maybe_const<Const, Vs>>>));

Helper function templates

template< __cartesian_product_common_arg R >
constexpr auto __cartesian_common_arg_end( R& r ) {
    if constexpr (ranges::common_range<R>)
(exposition
        return ranges::end(r);                                    (9)
only*)
    else
        return ranges::begin(r) + ranges::distance(r);
}

So here’s the tea, item by item πŸ“

  1. cartesian_product_view is a range adaptor that takes n views, where n > 0, and produces a view of tuples calculated by the n-ary cartesian product of the provided ranges. The size of produced view is a multiple of sizes of provided ranges, while each element is a tuple (of references) of the size n.
  2. views::cartesian_product is a customization point object.
    • When calling with no argument, views::cartesian_product() is expression-equivalent to views::single(std::tuple()).
    • Otherwise, views::cartesian_product(rs...) is expression-equivalent to ranges::cartesian_product_view<views::all_t<decltype((rs))>...>(rs...).
  3. Determines if cartesian_product is a random access range (see also random_access_range).
  4. Determines if cartesian_product is a common range (see also common_range).
  5. Determines if cartesian_product is a bidirectional range (see also bidirectional_range).
  6. Determines if cartesian_product satisfies the helper concept __cartesian_product_is_common (see also common_range).
  7. Determines if cartesian_product is a sized range (see also sized_range).
  8. Determines if cartesian_product uses sized sentinel.
  9. Returns the end of the produced view. Participates in overload resolution only if cartesian_product satisfies the helper concept __cartesian_product_common_arg.

The First range passed to cartesian_product_view is treated specially, since it is only passed through a single time. As a result, several constraints are relaxed on it:

  • First is an input_range instead of forward_range;
  • First does not have to be a sized_range in order for the cartesian_product_view to be random_access_range or common_range;
  • First does not have to be common_range in order for the cartesian_product_view to be bidirectional_range.

πŸ’… Member functions πŸ’…

  • constructor β€” constructs a cartesian_product_view. (C++23) (public member function)
  • begin β€” returns an iterator to the beginning. (C++23) (public member function)
  • end β€” returns an iterator or a sentinel to the end. (C++23) (public member function)
  • size β€” returns the number of elements. Provided only if the underlying (adapted) range satisfies sized_range. (C++23) (public member function)

Inherited from std::ranges::view_interface

  • empty β€” returns whether the derived view is empty. Provided if it satisfies sized_range or forward_range. (C++20) (public member function of std::ranges::view_interface<D>)
  • cbegin β€” returns a constant iterator to the beginning of the range. (C++23) (public member function of std::ranges::view_interface<D>)
  • cend β€” returns a sentinel for the constant iterator of the range. (C++23) (public member function of std::ranges::view_interface<D>)
  • operator bool β€” returns whether the derived view is not empty. Provided if ranges::empty is applicable to it. (C++20) (public member function of std::ranges::view_interface<D>)
  • front β€” returns the first element in the derived view. Provided if it satisfies forward_range. (C++20) (public member function of std::ranges::view_interface<D>)
  • back β€” returns the last element in the derived view. Provided if it satisfies bidirectional_range and common_range. (C++20) (public member function of std::ranges::view_interface<D>)
  • operator[] β€” returns the n^th element in the derived view. Provided if it satisfies random_access_range. (C++20) (public member function of std::ranges::view_interface<D>)

πŸŽ€ Deduction guides πŸŽ€

That’s the heading, bestie β€” no extra details listed here. πŸ’€


πŸ¦‹ Nested classes πŸ¦‹

  • iterator β€” the iterator type. (C++23) (exposition-only member class template*)

🌈 Notes 🌈

  • Feature-test macro β€” __cpp_lib_ranges_cartesian_product
  • Value β€” 202207L
  • Std β€” (C++23)
  • Feature β€” std::ranges::cartesian_product_view

πŸ”₯ Example πŸ”₯

// Run this code

#include <array>
#include <iostream>
#include <list>
#include <ranges>
#include <string>
#include <vector>

void print(std::tuple<char const&, int const&, std::string const&> t, int pos)
{
    const auto& [a, b, c] = t;
    std::cout << '(' << a << ' ' << b << ' ' << c << ')' << (pos % 4 ? " " : "\n");
}

int main()
{
    const auto x = std::array{'A', 'B'};
    const auto y = std::vector{1, 2, 3};
    const auto z = std::list<std::string>{"Ξ±", "Ξ²", "Ξ³", "Ξ΄"};

    for (int i{1}; auto const& tuple : std::views::cartesian_product(x, y, z))
        print(tuple, i++);
}

πŸ“ Output πŸ“

(A 1 Ξ±) (A 1 Ξ²) (A 1 Ξ³) (A 1 Ξ΄)
(A 2 Ξ±) (A 2 Ξ²) (A 2 Ξ³) (A 2 Ξ΄)
(A 3 Ξ±) (A 3 Ξ²) (A 3 Ξ³) (A 3 Ξ΄)
(B 1 Ξ±) (B 1 Ξ²) (B 1 Ξ³) (B 1 Ξ΄)
(B 2 Ξ±) (B 2 Ξ²) (B 2 Ξ³) (B 2 Ξ΄)
(B 3 Ξ±) (B 3 Ξ²) (B 3 Ξ³) (B 3 Ξ΄)

🧚 References 🧚

  • C++23 standard (ISO/IEC 14882:2023):
  • 26.7.31 Cartesian product view [range.stride]

πŸ‘‘ See also πŸ‘‘

  • ranges::zip_view β€” a view consisting of tuples of references to corresponding elements of the adapted views. (C++23) (class template)
  • views::zip β€” a view consisting of tuples of references to corresponding elements of the adapted views. (C++23) (customization point object)

Source/version/date: cppreference.com, 2024.06.10, std::ranges...product_view(3) β€” bye bestie, go make something iconic πŸ’–βœ¨πŸŒΈ

πŸ“¦ where this page comes from