628 lines
37 KiB
Markdown
628 lines
37 KiB
Markdown
[range.cartesian]
|
||
|
||
# 25 Ranges library [[ranges]](./#ranges)
|
||
|
||
## 25.7 Range adaptors [[range.adaptors]](range.adaptors#range.cartesian)
|
||
|
||
### 25.7.33 Cartesian product view [range.cartesian]
|
||
|
||
#### [25.7.33.1](#overview) Overview [[range.cartesian.overview]](range.cartesian.overview)
|
||
|
||
[1](#overview-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16562)
|
||
|
||
cartesian_product_view takes any non-zero number of ranges n and
|
||
produces a view of tuples calculated by
|
||
the n-ary cartesian product of the provided ranges[.](#overview-1.sentence-1)
|
||
|
||
[2](#overview-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16567)
|
||
|
||
The name views::cartesian_product denotes a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#overview-2.sentence-1)
|
||
|
||
Given a pack of subexpressions Es,
|
||
the expression views::cartesian_product(Es...) is expression-equivalent to
|
||
|
||
- [(2.1)](#overview-2.1)
|
||
|
||
views::single(tuple()) if Es is an empty pack,
|
||
|
||
- [(2.2)](#overview-2.2)
|
||
|
||
otherwise,cartesian_product_view<views::all_t<decltype((Es))>...>(Es...)[.](#overview-2.sentence-2)
|
||
|
||
[3](#overview-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16581)
|
||
|
||
[*Example [1](#overview-example-1)*: vector<int> v { 0, 1, 2 };for (auto&& [a, b, c] : views::cartesian_product(v, v, v)) { cout << a << ' ' << b << ' ' << c << '\n';}// The above prints// 0 0 0// 0 0 1// 0 0 2// 0 1 0// 0 1 1// ... â *end example*]
|
||
|
||
#### [25.7.33.2](#view) Class template cartesian_product_view [[range.cartesian.view]](range.cartesian.view)
|
||
|
||
[ð](#lib:cartesian_product_view_)
|
||
|
||
namespace std::ranges {template<bool Const, class First, class... Vs>concept [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]") = // *exposition only*([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, First>> && ... &&([random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, Vs>>&& [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*<Const, Vs>>)); template<class R>concept [*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]") = // *exposition only*[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<R> || ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> && [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<R>); template<bool Const, class First, class... Vs>concept [*cartesian-product-is-bidirectional*](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]") = // *exposition only*([bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, First>> && ... &&([bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, Vs>>&& [*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<*maybe-const*<Const, Vs>>)); template<class First, class...>concept [*cartesian-product-is-common*](#concept:cartesian-product-is-common "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]") = // *exposition only*[*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<First>; template<class... Vs>concept [*cartesian-product-is-sized*](#concept:cartesian-product-is-sized "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]") = // *exposition only*([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<Vs> && ...); template<bool Const, template<class> class FirstSent, class First, class... Vs>concept [*cartesian-is-sized-sentinel*](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]") = // *exposition only*([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<FirstSent<*maybe-const*<Const, First>>,
|
||
iterator_t<*maybe-const*<Const, First>>> && ...&& ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<*maybe-const*<Const, Vs>>&& [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<iterator_t<*maybe-const*<Const, Vs>>,
|
||
iterator_t<*maybe-const*<Const, Vs>>>)); template<[*cartesian-product-common-arg*](#concept:cartesian-product-common-arg "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]") R>constexpr auto *cartesian-common-arg-end*(R& r) { // *exposition only*if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<R>) {return ranges::end(r); } else {return ranges::begin(r) + ranges::distance(r); }}template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") First, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")... Vs>requires ([view](range.view#concept:view "25.4.5 Views [range.view]")<First> && ... && [view](range.view#concept:view "25.4.5 Views [range.view]")<Vs>)class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {private: tuple<First, Vs...> *bases_*; // *exposition only*// [[range.cartesian.iterator]](#iterator "25.7.33.3 Class template cartesian_product_view::iterator"), class template cartesian_product_view::*iterator*template<bool Const> class *iterator*; // *exposition only*public:constexpr cartesian_product_view() = default; constexpr explicit cartesian_product_view(First first_base, Vs... bases); constexpr *iterator*<false> begin()requires (<First> || ... || <Vs>); constexpr *iterator*<true> begin() constrequires ([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>); 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() constrequires [*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...>; constexpr default_sentinel_t end() const noexcept; 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() constrequires [*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...>; }; template<class... Vs> cartesian_product_view(Vs&&...) -> cartesian_product_view<views::all_t<Vs>...>;}
|
||
|
||
[ð](#lib:cartesian_product_view,constructor)
|
||
|
||
`constexpr explicit cartesian_product_view(First first_base, Vs... bases);
|
||
`
|
||
|
||
[1](#view-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16685)
|
||
|
||
*Effects*: Initializes *bases_* with std::move(first_base), std::move(bases)...[.](#view-1.sentence-1)
|
||
|
||
[ð](#lib:begin,cartesian_product_view)
|
||
|
||
`constexpr iterator<false> begin()
|
||
requires (<First> || ... || <Vs>);
|
||
`
|
||
|
||
[2](#view-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16698)
|
||
|
||
*Effects*: Equivalent to:return *iterator*<false>(*this, *tuple-transform*(ranges::begin, *bases_*));
|
||
|
||
[ð](#lib:begin,cartesian_product_view_)
|
||
|
||
`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>);
|
||
`
|
||
|
||
[3](#view-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16713)
|
||
|
||
*Effects*: Equivalent to:return *iterator*<true>(*this, *tuple-transform*(ranges::begin, *bases_*));
|
||
|
||
[ð](#lib:end,cartesian_product_view)
|
||
|
||
`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...>;
|
||
`
|
||
|
||
[4](#view-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16731)
|
||
|
||
Let:
|
||
|
||
- [(4.1)](#view-4.1)
|
||
|
||
*is-const* be true for the const-qualified overload, andfalse otherwise;
|
||
|
||
- [(4.2)](#view-4.2)
|
||
|
||
*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
|
||
|
||
- [(4.3)](#view-4.3)
|
||
|
||
*begin-or-first-end*(rng) be expression-equivalent to*is-empty* ? ranges::begin(rng) : *cartesian-common-arg-end*(rng) if rng is the first underlying range andranges::begin(rng) otherwise[.](#view-4.sentence-1)
|
||
|
||
[5](#view-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16749)
|
||
|
||
*Effects*: Equivalent to:*iterator*<*is-const*> it(*this, *tuple-transform*([](auto& rng){ return *begin-or-first-end*(rng); }, *bases_*));return it;
|
||
|
||
[ð](#lib:end,cartesian_product_view_)
|
||
|
||
`constexpr default_sentinel_t end() const noexcept;
|
||
`
|
||
|
||
[6](#view-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16765)
|
||
|
||
*Returns*: default_sentinel[.](#view-6.sentence-1)
|
||
|
||
[ð](#lib:size,cartesian_product_view)
|
||
|
||
`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...>;
|
||
`
|
||
|
||
[7](#view-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16779)
|
||
|
||
The return type is an implementation-defined unsigned-integer-like type[.](#view-7.sentence-1)
|
||
|
||
[8](#view-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16782)
|
||
|
||
*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[.](#view-8.sentence-1)
|
||
|
||
[9](#view-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16788)
|
||
|
||
Let p be the product of the sizes of all the ranges in *bases_*[.](#view-9.sentence-1)
|
||
|
||
[10](#view-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16791)
|
||
|
||
*Preconditions*: p can be represented by the return type[.](#view-10.sentence-1)
|
||
|
||
[11](#view-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16795)
|
||
|
||
*Returns*: p[.](#view-11.sentence-1)
|
||
|
||
#### [25.7.33.3](#iterator) Class template cartesian_product_view::*iterator* [[range.cartesian.iterator]](range.cartesian.iterator)
|
||
|
||
[ð](#lib:cartesian_product_view::iterator)
|
||
|
||
namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") First, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")... Vs>requires ([view](range.view#concept:view "25.4.5 Views [range.view]")<First> && ... && [view](range.view#concept:view "25.4.5 Views [range.view]")<Vs>)template<bool Const>class cartesian_product_view<First, Vs...>::*iterator* {public:using iterator_category = input_iterator_tag; using iterator_concept = *see below*; using value_type = tuple<range_value_t<*maybe-const*<Const, First>>,
|
||
range_value_t<*maybe-const*<Const, Vs>>...>; using reference = tuple<range_reference_t<*maybe-const*<Const, First>>,
|
||
range_reference_t<*maybe-const*<Const, Vs>>...>; using difference_type = *see below*; *iterator*() = default; constexpr *iterator*(*iterator*<!Const> i) requires Const &&([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<First>, iterator_t<const First>> &&... && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<Vs>, iterator_t<const Vs>>); constexpr auto operator*() const; constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*maybe-const*<Const, First>>; constexpr *iterator*& operator--()requires [*cartesian-product-is-bidirectional*](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>; constexpr *iterator* operator--(int)requires [*cartesian-product-is-bidirectional*](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>; constexpr *iterator*& operator+=(difference_type x)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>; constexpr *iterator*& operator-=(difference_type x)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>; constexpr reference operator[](difference_type n) constrequires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y)requires [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<iterator_t<*maybe-const*<Const, First>>>; friend constexpr bool operator==(const *iterator*& x, default_sentinel_t); friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [*all-random-access*](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]")<Const, First, Vs...>; friend constexpr *iterator* operator+(const *iterator*& x, difference_type y)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>; friend constexpr *iterator* operator+(difference_type x, const *iterator*& y)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>; friend constexpr *iterator* operator-(const *iterator*& x, difference_type y)requires [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [*cartesian-is-sized-sentinel*](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, iterator_t, First, Vs...>; friend constexpr difference_type operator-(const *iterator*& i, default_sentinel_t)requires [*cartesian-is-sized-sentinel*](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, sentinel_t, First, Vs...>; friend constexpr difference_type operator-(default_sentinel_t, const *iterator*& i)requires [*cartesian-is-sized-sentinel*](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, sentinel_t, First, Vs...>; friend constexpr auto iter_move(const *iterator*& i) noexcept(*see below*); friend constexpr void iter_swap(const *iterator*& l, const *iterator*& r) noexcept(*see below*)requires ([indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]")<iterator_t<*maybe-const*<Const, First>>> && ... &&[indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]")<iterator_t<*maybe-const*<Const, Vs>>>); private:using *Parent* = *maybe-const*<Const, cartesian_product_view>; // *exposition only**Parent** *parent_* = nullptr; // *exposition only* tuple<iterator_t<*maybe-const*<Const, First>>,
|
||
iterator_t<*maybe-const*<Const, Vs>>...> *current_*; // *exposition only*template<size_t N = sizeof...(Vs)>constexpr void *next*(); // *exposition only*template<size_t N = sizeof...(Vs)>constexpr void *prev*(); // *exposition only*template<class Tuple>constexpr difference_type *distance-from*(const Tuple& t) const; // *exposition only*constexpr *iterator*(*Parent*& parent, tuple<iterator_t<*maybe-const*<Const, First>>,
|
||
iterator_t<*maybe-const*<Const, Vs>>...> current); // *exposition only*};}
|
||
|
||
[1](#iterator-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16891)
|
||
|
||
*iterator*::iterator_concept is defined as follows:
|
||
|
||
- [(1.1)](#iterator-1.1)
|
||
|
||
If [*cartesian-product-is-random-access*](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...> is modeled,
|
||
then iterator_concept denotes random_access_iterator_tag[.](#iterator-1.1.sentence-1)
|
||
|
||
- [(1.2)](#iterator-1.2)
|
||
|
||
Otherwise,
|
||
if [*cartesian-product-is-bidirectional*](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...> is modeled,
|
||
then iterator_concept denotes bidirectional_iterator_tag[.](#iterator-1.2.sentence-1)
|
||
|
||
- [(1.3)](#iterator-1.3)
|
||
|
||
Otherwise,
|
||
if *maybe-const*<Const, First> models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"),
|
||
then iterator_concept denotes forward_iterator_tag[.](#iterator-1.3.sentence-1)
|
||
|
||
- [(1.4)](#iterator-1.4)
|
||
|
||
Otherwise, iterator_concept denotes input_iterator_tag[.](#iterator-1.4.sentence-1)
|
||
|
||
[2](#iterator-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16911)
|
||
|
||
*iterator*::difference_type is
|
||
an implementation-defined
|
||
signed-integer-like type[.](#iterator-2.sentence-1)
|
||
|
||
[3](#iterator-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16916)
|
||
|
||
*Recommended practice*: *iterator*::difference_type should be
|
||
the smallest signed-integer-like type
|
||
that is sufficiently wide to store
|
||
the product of the maximum sizes of all underlying ranges
|
||
if such a type exists[.](#iterator-3.sentence-1)
|
||
|
||
[ð](#lib:next,cartesian_product_view)
|
||
|
||
`template<size_t N = sizeof...(Vs)>
|
||
constexpr void next();
|
||
`
|
||
|
||
[4](#iterator-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16931)
|
||
|
||
*Effects*: Equivalent to:auto& it = std::get<N>(*current_*);++it;if constexpr (N > 0) {if (it == ranges::end(std::get<N>(*parent_*->*bases_*))) { it = ranges::begin(std::get<N>(*parent_*->*bases_*)); *next*<N - 1>(); }}
|
||
|
||
[ð](#lib:prev,cartesian_product_view)
|
||
|
||
`template<size_t N = sizeof...(Vs)>
|
||
constexpr void prev();
|
||
`
|
||
|
||
[5](#iterator-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16953)
|
||
|
||
*Effects*: Equivalent to:auto& it = std::get<N>(*current_*);if constexpr (N > 0) {if (it == ranges::begin(std::get<N>(*parent_*->*bases_*))) { it = *cartesian-common-arg-end*(std::get<N>(*parent_*->*bases_*)); *prev*<N - 1>(); }}--it;
|
||
|
||
[ð](#lib:distance-from,cartesian_product_view)
|
||
|
||
`template<class Tuple>
|
||
constexpr difference_type distance-from(const Tuple& t) const;
|
||
`
|
||
|
||
[6](#iterator-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16975)
|
||
|
||
Let:
|
||
|
||
- [(6.1)](#iterator-6.1)
|
||
|
||
*scaled-size*(N) be the product ofstatic_cast<difference_type>(ranges::size(std::get<N>(*parent_*->*bases_*))) andscaled-size(N+1) if N ⤠sizeof...(Vs), otherwise static_cast<difference_type>(1);
|
||
|
||
- [(6.2)](#iterator-6.2)
|
||
|
||
*scaled-distance*(N) be the product ofstatic_cast<difference_type>(std::get<N>(*current_*) - std::get<N>(t)) and scaled-size(N+1); and
|
||
|
||
- [(6.3)](#iterator-6.3)
|
||
|
||
*scaled-sum* be the sum of *scaled-distance*(N) for every integer 0 ⤠N ⤠sizeof...(Vs)[.](#iterator-6.sentence-1)
|
||
|
||
[7](#iterator-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16991)
|
||
|
||
*Preconditions*: *scaled-sum* can be represented by difference_type[.](#iterator-7.sentence-1)
|
||
|
||
[8](#iterator-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L16995)
|
||
|
||
*Returns*: *scaled-sum*[.](#iterator-8.sentence-1)
|
||
|
||
[ð](#lib:cartesian_product_view::iterator,constructor)
|
||
|
||
`constexpr iterator(Parent& parent, tuple<iterator_t<maybe-const<Const, First>>,
|
||
iterator_t<maybe-const<Const, Vs>>...> current);
|
||
`
|
||
|
||
[9](#iterator-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17007)
|
||
|
||
*Effects*: Initializes*parent_* with addressof(parent) and*current_* with std::move(current)[.](#iterator-9.sentence-1)
|
||
|
||
[ð](#lib:cartesian_product_view::iterator,constructor_)
|
||
|
||
`constexpr iterator(iterator<!Const> i) requires Const &&
|
||
([convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<First>, iterator_t<const First>> &&
|
||
... && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<Vs>, iterator_t<const Vs>>);
|
||
`
|
||
|
||
[10](#iterator-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17022)
|
||
|
||
*Effects*: Initializes*parent_* with i.*parent_* and*current_* with std::move(i.*current_*)[.](#iterator-10.sentence-1)
|
||
|
||
[ð](#lib:operator*,cartesian_product_view::iterator)
|
||
|
||
`constexpr auto operator*() const;
|
||
`
|
||
|
||
[11](#iterator-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17035)
|
||
|
||
*Effects*: Equivalent to:return *tuple-transform*([](auto& i) -> decltype(auto) { return *i; }, *current_*);
|
||
|
||
[ð](#lib:operator++,cartesian_product_view::iterator)
|
||
|
||
`constexpr iterator& operator++();
|
||
`
|
||
|
||
[12](#iterator-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17049)
|
||
|
||
*Effects*: Equivalent to:*next*();return *this;
|
||
|
||
[ð](#lib:operator++,cartesian_product_view::iterator_)
|
||
|
||
`constexpr void operator++(int);
|
||
`
|
||
|
||
[13](#iterator-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17064)
|
||
|
||
*Effects*: Equivalent to ++*this[.](#iterator-13.sentence-1)
|
||
|
||
[ð](#lib:operator++,cartesian_product_view::iterator__)
|
||
|
||
`constexpr iterator operator++(int) requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<maybe-const<Const, First>>;
|
||
`
|
||
|
||
[14](#iterator-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17075)
|
||
|
||
*Effects*: Equivalent to:auto tmp = *this;++*this;return tmp;
|
||
|
||
[ð](#lib:operator--,cartesian_product_view::iterator)
|
||
|
||
`constexpr iterator& operator--()
|
||
requires [cartesian-product-is-bidirectional](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[15](#iterator-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17092)
|
||
|
||
*Effects*: Equivalent to:*prev*();return *this;
|
||
|
||
[ð](#lib:operator--,cartesian_product_view::iterator_)
|
||
|
||
`constexpr iterator operator--(int)
|
||
requires [cartesian-product-is-bidirectional](#concept:cartesian-product-is-bidirectional "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[16](#iterator-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17108)
|
||
|
||
*Effects*: Equivalent to:auto tmp = *this;--*this;return tmp;
|
||
|
||
[ð](#lib:operator+=,cartesian_product_view::iterator)
|
||
|
||
`constexpr iterator& operator+=(difference_type x)
|
||
requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[17](#iterator-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17125)
|
||
|
||
Let orig be the value of *this before the call[.](#iterator-17.sentence-1)
|
||
|
||
Let ret be:
|
||
|
||
- [(17.1)](#iterator-17.1)
|
||
|
||
If x > 0,
|
||
the value of *this had *next* been called x times[.](#iterator-17.1.sentence-1)
|
||
|
||
- [(17.2)](#iterator-17.2)
|
||
|
||
Otherwise, if x < 0,
|
||
the value of *this had *prev* been called -x times[.](#iterator-17.2.sentence-1)
|
||
|
||
- [(17.3)](#iterator-17.3)
|
||
|
||
Otherwise, orig[.](#iterator-17.3.sentence-1)
|
||
|
||
[18](#iterator-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17140)
|
||
|
||
*Preconditions*: x is in the range[ranges::distance(*this, ranges::begin(**parent_*)),
|
||
ranges::distance(*this, ranges::end(**parent_*))][.](#iterator-18.sentence-1)
|
||
|
||
[19](#iterator-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17146)
|
||
|
||
*Effects*: Sets the value of *this to ret[.](#iterator-19.sentence-1)
|
||
|
||
[20](#iterator-20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17150)
|
||
|
||
*Returns*: *this[.](#iterator-20.sentence-1)
|
||
|
||
[21](#iterator-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17154)
|
||
|
||
*Complexity*: Constant[.](#iterator-21.sentence-1)
|
||
|
||
[ð](#lib:operator-=,cartesian_product_view::iterator)
|
||
|
||
`constexpr iterator& operator-=(difference_type x)
|
||
requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[22](#iterator-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17166)
|
||
|
||
*Effects*: Equivalent to:*this += -x;return *this;
|
||
|
||
[ð](#lib:operator%5b%5d,cartesian_product_view::iterator)
|
||
|
||
`constexpr reference operator[](difference_type n) const
|
||
requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[23](#iterator-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17182)
|
||
|
||
*Effects*: Equivalent to: return *((*this) + n);
|
||
|
||
[ð](#lib:operator==,cartesian_product_view::iterator)
|
||
|
||
`friend constexpr bool operator==(const iterator& x, const iterator& y)
|
||
requires [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<iterator_t<maybe-const<Const, First>>>;
|
||
`
|
||
|
||
[24](#iterator-24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17194)
|
||
|
||
*Effects*: Equivalent to: return x.*current_* == y.*current_*;
|
||
|
||
[ð](#lib:operator==,cartesian_product_view::iterator_)
|
||
|
||
`friend constexpr bool operator==(const iterator& x, default_sentinel_t);
|
||
`
|
||
|
||
[25](#iterator-25)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17205)
|
||
|
||
*Returns*: true if std::get<i>(x.*current_*) == ranges::end(std::get<i>(x.*parent_*->*bases_*)) is true for any integer 0 ⤠i ⤠sizeof...(Vs);
|
||
otherwise, false[.](#iterator-25.sentence-1)
|
||
|
||
[ð](#lib:operator%3c=%3e,cartesian_product_view::iterator)
|
||
|
||
`friend constexpr auto operator<=>(const iterator& x, const iterator& y)
|
||
requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[26](#iterator-26)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17220)
|
||
|
||
*Effects*: Equivalent to: return x.*current_* <=> y.*current_*;
|
||
|
||
[ð](#lib:operator+,cartesian_product_view::iterator)
|
||
|
||
`friend constexpr iterator operator+(const iterator& x, difference_type y)
|
||
requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[27](#iterator-27)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17232)
|
||
|
||
*Effects*: Equivalent to: return *iterator*(x) += y;
|
||
|
||
[ð](#lib:operator+,cartesian_product_view::iterator_)
|
||
|
||
`friend constexpr iterator operator+(difference_type x, const iterator& y)
|
||
requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[28](#iterator-28)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17244)
|
||
|
||
*Effects*: Equivalent to: return y + x;
|
||
|
||
[ð](#lib:operator-,cartesian_product_view::iterator)
|
||
|
||
`friend constexpr iterator operator-(const iterator& x, difference_type y)
|
||
requires [cartesian-product-is-random-access](#concept:cartesian-product-is-random-access "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, First, Vs...>;
|
||
`
|
||
|
||
[29](#iterator-29)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17256)
|
||
|
||
*Effects*: Equivalent to: return *iterator*(x) -= y;
|
||
|
||
[ð](#lib:operator-,cartesian_product_view::iterator_)
|
||
|
||
`friend constexpr difference_type operator-(const iterator& x, const iterator& y)
|
||
requires [cartesian-is-sized-sentinel](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, iterator_t, First, Vs...>;
|
||
`
|
||
|
||
[30](#iterator-30)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17268)
|
||
|
||
*Effects*: Equivalent to: return x.*distance-from*(y.*current_*);
|
||
|
||
[ð](#lib:operator-,cartesian_product_view::iterator__)
|
||
|
||
`friend constexpr difference_type operator-(const iterator& i, default_sentinel_t)
|
||
requires [cartesian-is-sized-sentinel](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, sentinel_t, First, Vs...>;
|
||
`
|
||
|
||
[31](#iterator-31)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17280)
|
||
|
||
Let *end-tuple* be an object of a type
|
||
that is a specialization of tuple, such that:
|
||
|
||
- [(31.1)](#iterator-31.1)
|
||
|
||
std::get<0>(*end-tuple*) has the same value asranges::end(std::get<0>(i.*parent_*->*bases_*));
|
||
|
||
- [(31.2)](#iterator-31.2)
|
||
|
||
std::get<N>(*end-tuple*) has the same value asranges::begin(std::get<N>(i.*parent_*->*bases_*)) for every integer 1 ⤠N ⤠sizeof...(Vs)[.](#iterator-31.sentence-1)
|
||
|
||
[32](#iterator-32)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17293)
|
||
|
||
*Effects*: Equivalent to: return i.*distance-from*(*end-tuple*);
|
||
|
||
[ð](#lib:operator-,cartesian_product_view::iterator___)
|
||
|
||
`friend constexpr difference_type operator-(default_sentinel_t s, const iterator& i)
|
||
requires [cartesian-is-sized-sentinel](#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, sentinel_t, First, Vs...>;
|
||
`
|
||
|
||
[33](#iterator-33)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17305)
|
||
|
||
*Effects*: Equivalent to: return -(i - s);
|
||
|
||
[ð](#lib:iter_move,cartesian_product_view::iterator)
|
||
|
||
`friend constexpr auto iter_move(const iterator& i) noexcept(see below);
|
||
`
|
||
|
||
[34](#iterator-34)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17316)
|
||
|
||
*Effects*: Equivalent to: return *tuple-transform*(ranges::iter_move, i.*current_*);
|
||
|
||
[35](#iterator-35)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17320)
|
||
|
||
*Remarks*: The exception specification is equivalent to
|
||
the logical and of the following expressions:
|
||
|
||
- [(35.1)](#iterator-35.1)
|
||
|
||
noexcept(ranges::iter_move(std::get<N>(i.*current_*))) for every integer
|
||
0 ⤠N ⤠sizeof...(Vs),
|
||
|
||
- [(35.2)](#iterator-35.2)
|
||
|
||
is_nothrow_move_constructible_v<range_rvalue_reference_t<*maybe-const*<Const, T>>>
|
||
for every type T in First, Vs...[.](#iterator-35.sentence-1)
|
||
|
||
[ð](#lib:iter_swap,cartesian_product_view::iterator)
|
||
|
||
`friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
|
||
requires ([indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]")<iterator_t<maybe-const<Const, First>>> && ... &&
|
||
[indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]")<iterator_t<maybe-const<Const, Vs>>>);
|
||
`
|
||
|
||
[36](#iterator-36)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17342)
|
||
|
||
*Effects*: For every integer 0 ⤠i ⤠sizeof...(Vs), performs:ranges::iter_swap(std::get<i>(l.*current_*), std::get<i>(r.*current_*))
|
||
|
||
[37](#iterator-37)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L17349)
|
||
|
||
*Remarks*: The exception specification is equivalent to the logical and of the following expressions:
|
||
|
||
- [(37.1)](#iterator-37.1)
|
||
|
||
noexcept(ranges::iter_swap(std::get<i>(l.*current_*), std::get<i>(r.*current_*))) for
|
||
every integer 0 ⤠i ⤠sizeof...(Vs)[.](#iterator-37.sentence-1)
|