12 KiB
[range.cartesian.view]
25 Ranges library [ranges]
25.7 Range adaptors [range.adaptors]
25.7.33 Cartesian product view [range.cartesian]
25.7.33.2 Class template cartesian_product_view [range.cartesian.view]
namespace std::ranges {template<bool Const, class First, class... Vs>concept cartesian-product-is-random-access = // exposition only(random_access_range<maybe-const<Const, First>> && ... &&(random_access_range<maybe-const<Const, Vs>>&& sized_range<maybe-const<Const, Vs>>)); templateconcept cartesian-product-common-arg = // exposition onlycommon_range || (sized_range && random_access_range); template<bool Const, class First, class... Vs>concept cartesian-product-is-bidirectional = // exposition only(bidirectional_range<maybe-const<Const, First>> && ... &&(bidirectional_range<maybe-const<Const, Vs>>&& cartesian-product-common-arg<maybe-const<Const, Vs>>)); template<class First, class...>concept cartesian-product-is-common = // exposition onlycartesian-product-common-arg; template<class... Vs>concept cartesian-product-is-sized = // exposition only(sized_range && ...); template<bool Const, template class FirstSent, class First, class... Vs>concept cartesian-is-sized-sentinel = // exposition only(sized_sentinel_for<FirstSent<maybe-const<Const, First>>,
iterator_t<maybe-const<Const, First>>> && ...&& (sized_range<maybe-const<Const, Vs>>&& sized_sentinel_for<iterator_t<maybe-const<Const, Vs>>,
iterator_t<maybe-const<Const, Vs>>>)); template<cartesian-product-common-arg R>constexpr auto cartesian-common-arg-end(R& r) { // exposition onlyif constexpr (common_range) {return ranges::end(r); } else {return ranges::begin(r) + ranges::distance(r); }}template<input_range First, forward_range... Vs>requires (view && ... && view)class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {private: tuple<First, Vs...> bases_; // exposition only// [range.cartesian.iterator], class template cartesian_product_view::iteratortemplate class iterator; // exposition onlypublic:constexpr cartesian_product_view() = default; constexpr explicit cartesian_product_view(First first_base, Vs... bases); constexpr iterator begin()requires ( || ... ||
); constexpr iterator begin() constrequires (range && ... && range); constexpr iterator end()requires ((
|| ... ||
) &&cartesian-product-is-common<First, Vs...>); constexpr iterator end() constrequires cartesian-product-is-common<const First, const Vs...>; constexpr default_sentinel_t end() const noexcept; constexpr see below size()requires cartesian-product-is-sized<First, Vs...>; constexpr see below size() constrequires cartesian-product-is-sized<const First, const Vs...>; }; template<class... Vs> cartesian_product_view(Vs&&...) -> cartesian_product_view<views::all_t...>;}
constexpr explicit cartesian_product_view(First first_base, Vs... bases);
Effects: Initializes bases_ with std::move(first_base), std::move(bases)....
constexpr iterator<false> begin() requires (<First> || ... || <Vs>);
Effects: Equivalent to:return iterator(*this, tuple-transform(ranges::begin, bases_));
constexpr iterator<true> begin() const requires ([range](range.range#concept:range "25.4.2 Ranges [range.range]")<const First> && ... && [range](range.range#concept:range "25.4.2 Ranges [range.range]")<const Vs>);
Effects: Equivalent to:return iterator(*this, tuple-transform(ranges::begin, bases_));
constexpr iterator<false> end() requires ((<First> || ... || <Vs>) && [cartesian-product-is-common](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<First, Vs...>); constexpr iterator<true> end() const requires [cartesian-product-is-common](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<const First, const Vs...>;
Let:
is-const be true for the const-qualified overload, andfalse otherwise;
is-empty be true if the expression ranges::empty(rng) is true for any rng among the underlying ranges except the first one andfalse otherwise; and
begin-or-first-end(rng) be expression-equivalent tois-empty ? ranges::begin(rng) : cartesian-common-arg-end(rng) if rng is the first underlying range andranges::begin(rng) otherwise.
Effects: Equivalent to:iterator<is-const> it(*this, tuple-transform([](auto& rng){ return begin-or-first-end(rng); }, bases_));return it;
constexpr default_sentinel_t end() const noexcept;
Returns: default_sentinel.
constexpr see below size() requires [cartesian-product-is-sized](#concept:cartesian-product-is-sized "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<First, Vs...>; constexpr see below size() const requires [cartesian-product-is-sized](#concept:cartesian-product-is-sized "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<const First, const Vs...>;
The return type is an implementation-defined unsigned-integer-like type.
Recommended practice: The return type should be the smallest unsigned-integer-like type that is sufficiently wide to store the product of the maximum sizes of all the underlying ranges, if such a type exists.
Let p be the product of the sizes of all the ranges in bases_.
Preconditions: p can be represented by the return type.
Returns: p.