From 01a83883e0a33c5a67b47e7cf072b454106f8f6f Mon Sep 17 00:00:00 2001
From: huixie90 Contents
cartesian_product_view
!common_range && (random_accessed_range && sized_range)
iter_swap
Customizations
Contents
1 Revision History
1.1 R6
-
!common_range && random_access_range && sized_range
bidirectional_range
+support for !common_range && random_access_range && sized_range
random_access_range
+support for !common_range && random_access_range && sized_range
1.2 R5
@@ -1013,6 +1014,7 @@
the first underlying range and
concat_view
checks the last
underlying range.
As per SG9 direction, this section is dropped.
!common_range && (random_accessed_range && sized_range)
In R0 version, concat_view
is
a common_range
if the last range
@@ -1074,7 +1076,8 @@
auto cv = views::concat(r | views::common, other_views...)
As per LEWG direction, the change proposed in this section is adopted +## Bidirectional Range
concat_view
can model
bidirectional_range
if the
underlying ranges satisfy the following conditions:
ranges::begin(n-1th range) + (ranges::size(n-1th range) - 1)
-in constant time, assuming n-1th range is not empty.
+in constant time, assuming n-1th range is not empty. However, as per
+LEWG’s direction,!common_range && random_access_range && sized_range
+is removed
Note that the last underlying range does not have to satisfy this
constraint because n-1 can never be the last underlying range. If
@@ -1110,9 +1115,8 @@ ranges::next(ranges::begin(r), ranges::end(r))
which implicitly requires random access to make the operation constant
-time. So it went with the second constraint. In this paper, both are
-supported.
-concat_view
can model
random_access_range
if the
underlying ranges satisfy the following conditions:
sized_range
common_range
-concat_view
can be
sized_range
if all the
underlying ranges model
sized_range
iter_swap
Customizationsiter_swap
This option was originally adopted in the paper. If all the combinations of the underlying iterators model @@ -1171,7 +1175,7 @@
It turned out that allowing swapping elements across heterogeneous ranges could result in lots of undesired behaviours.
-If the iter_swap
customization is removed, the above examples are no longer an issue
@@ -1189,7 +1193,7 @@
iter_swap
customizations.
-iter_swap
Only If
They Have the Same TypeThis option was suggested by Tomasz in the SG9 mailing list. The idea @@ -1211,7 +1215,7 @@
views::concat
has been
implemented in [range-v3], with
equivalent semantics as proposed here. The authors also implemented a
@@ -1280,52 +1284,6 @@
Add the following to 26.7.5 -[range.adaptor.helpers]
-
- namespace std::ranges {
- // [...]+ template<class R>
-+ concept common-arg = // exposition only
-+ common_range<R> || (sized_range<R> && random_access_range<R>);
-
- // [...] }
Modify the following in 26.7.32.2 -[range.cartesian.view]
-
- namespace std::ranges {
- // [...]- template<class R>
-- concept cartesian-product-common-arg = // exposition only
-- common_range<R> || (sized_range<R> && random_access_range<R>);
-
-
- 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>>));
-+ && common-arg<maybe-const<Const, Vs>>));
-
-
- template<class First, class... Vs>
- concept cartesian-product-is-common = // exposition only- cartesian-product-common-arg<First>;
-+ common-arg<First>;
-
-
- // [...]
-- template<cartesian-product-common-arg R>
-+ template<common-arg R>
-
- constexpr auto cartesian-common-arg-end(R& r) { // exposition only
- if constexpr (common_range<R>) {
- return ranges::end(r);
- } else {
- return ranges::begin(r) + ranges::distance(r);
- }
- }
- // [...] }
concat
Add the following subclause to 26.7
@@ -1357,115 +1315,115 @@ [Example: 1
The
exposition-only
2
The exposition-only
3
Let 4
Let 5
Effects: Initializes
6
Effects: Let
@@ -1508,12 +1466,12 @@ 7
Effects: Let
@@ -1526,142 +1484,142 @@ 8
Effects: Equivalent to: 1
3
Effects: Equivalent to: 4
Effects: Equivalent to: 5
Effects: Equivalent to: 6
Effects: Equivalent to: 7
Effects: Initializes
@@ -1805,9 +1756,9 @@ 8
Effects: Initializes
@@ -1816,7 +1767,7 @@ 9
Preconditions:
@@ -1824,11 +1775,11 @@ 10
Effects: Equivalent to: 11
Preconditions:
@@ -1838,27 +1789,27 @@ 14
Effects: Equivalent to: 15
Preconditions:
@@ -1868,20 +1819,20 @@ 17
Effects: Equivalent to: 18
Preconditions:
@@ -1891,30 +1842,30 @@ 22
Preconditions: 23
Effects: Equivalent to: 24
Preconditions: 25
Effects: Equivalent to: 26
Preconditions: 28
Effects: Equivalent to: 29
Preconditions: 30
Effects: Equivalent to: 33
Preconditions: (34.2)
otherwise, if
(34.3)
otherwise, equivalent to: 35
Preconditions: 37
Remarks: Let 38
Effects: Equivalent to: 39
Remarks: Let 40
Preconditions: 41
Effects: Equivalent to: 42
Remarks: The exception specification is equivalent to: 43
Preconditions: 44
Effects: Equivalent to: 45
Remarks: The exception specification is equivalent to where 46
Remarks: The expression in the requires-clause is equivalent
to Add the following macro definition to 17.3.2
@@ -2110,7 +2063,7 @@ ?.?.?.1
concat_view(Es...)
::vector<int> v1{1,2,3}, v2{4,5}, v3{};
- std::array a{6,7,8};
- stdauto s = std::views::single(9);
-for(auto&& i : std::views::concat(v1, v2, v3, a, s)){
-::cout << i << ' '; // prints: 1 2 3 4 5 6 7 8 9
- std}
::vector<int> v1{1,2,3}, v2{4,5}, v3{};
+ std::array a{6,7,8};
+ stdauto s = std::views::single(9);
+for(auto&& i : std::views::concat(v1, v2, v3, a, s)){
+::cout << i << ' '; // prints: 1 2 3 4 5 6 7 8 9
+ std}
?.?.?.2 Class template
-concat_view
[range.concat.view]namespace std::ranges {
-
-template <class... Rs>
- using concat-reference-t = common_reference_t<range_reference_t<Rs>...>; // exposition only
-
-template <class... Rs>
- using concat-value-t = common_type_t<range_value_t<Rs>...>; // exposition only
-
-template <class... Rs>
- using concat-rvalue-reference-t = common_reference_t<range_rvalue_reference_t<Rs>...>; // exposition only
-
-template <class... Rs>
- concept concat-indirectly-readable = see below; // exposition only
-
-template <class... Rs>
- concept concatable = see below; // exposition only
-
-template <bool Const, class... Rs>
- concept concat-is-random-access = see below; // exposition only
-
-template <bool Const, class... Rs>
- concept concat-is-bidirectional = see below; // exposition only
-
-template <input_range... Views>
- requires (view<Views> && ...) && (sizeof...(Views) > 0) &&
- <Views...>
- concatableclass concat_view : public view_interface<concat_view<Views...>> {
- <Views...> views_; // exposition only
- tuple
-template <bool Const>
- class iterator; // exposition only
-
-public:
- constexpr concat_view() = default;
-
-constexpr explicit concat_view(Views... views);
-
-constexpr iterator<false> begin() requires(!(simple-view<Views> && ...));
-
-constexpr iterator<true> begin() const
- requires((range<const Views> && ...) && concatable<const Views...>);
-
-constexpr auto end() requires(!(simple-view<Views> && ...));
-
-constexpr auto end() const requires(range<const Views>&&...);
-
-constexpr auto size() requires(sized_range<Views>&&...);
-
-constexpr auto size() const requires(sized_range<const Views>&&...);
- };
-
-template <class... R>
- (R&&...) -> concat_view<views::all_t<R>...>;
- concat_view}
template <class... Rs>
-concept concat-indirectly-readable = see below; // exposition only
namespace std::ranges {
+
+template <class... Rs>
+ using concat-reference-t = common_reference_t<range_reference_t<Rs>...>; // exposition only
+
+template <class... Rs>
+ using concat-value-t = common_type_t<range_value_t<Rs>...>; // exposition only
+
+template <class... Rs>
+ using concat-rvalue-reference-t = common_reference_t<range_rvalue_reference_t<Rs>...>; // exposition only
+
+template <class... Rs>
+ concept concat-indirectly-readable = see below; // exposition only
+
+template <class... Rs>
+ concept concatable = see below; // exposition only
+
+template <bool Const, class... Rs>
+ concept concat-is-random-access = see below; // exposition only
+
+template <bool Const, class... Rs>
+ concept concat-is-bidirectional = see below; // exposition only
+
+template <input_range... Views>
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) &&
+ <Views...>
+ concatableclass concat_view : public view_interface<concat_view<Views...>> {
+ <Views...> views_; // exposition only
+ tuple
+template <bool Const>
+ class iterator; // exposition only
+
+public:
+ constexpr concat_view() = default;
+
+constexpr explicit concat_view(Views... views);
+
+constexpr iterator<false> begin() requires(!(simple-view<Views> && ...));
+
+constexpr iterator<true> begin() const
+ requires((range<const Views> && ...) && concatable<const Views...>);
+
+constexpr auto end() requires(!(simple-view<Views> && ...));
+
+constexpr auto end() const requires(range<const Views>&&...);
+
+constexpr auto size() requires(sized_range<Views>&&...);
+
+constexpr auto size() const requires(sized_range<const Views>&&...);
+ };
+
+template <class... R>
+ (R&&...) -> concat_view<views::all_t<R>...>;
+ concat_view}
template <class... Rs>
+concept concat-indirectly-readable = see below; // exposition only
concat-indirectly-readable
concept is equivalent to:template <class Ref, class RRef, class It>
-concept concat-indirectly-readable-impl = // exposition only
-requires (const It it) {
-{ *it } -> convertible_to<Ref>;
- { ranges::iter_move(it) } -> convertible_to<RRef>;
- };
-
-template <class... Rs>
-concept concat-indirectly-readable = // exposition only
-<concat-reference-t<Rs...>&&,
- common_reference_with<Rs...>&> &&
- concat-value-t<concat-reference-t<Rs...>&&,
- common_reference_with<Rs...>&&> &&
- concat-rvalue-reference-t<concat-rvalue-reference-t<Rs...>&&,
- common_reference_with<Rs...> const&> &&
- concat-value-t(concat-indirectly-readable-impl<concat-reference-t<Rs...>,
- <Rs...>,
- concat-rvalue-reference-t<Rs>> && ...); iterator_t
template <class Ref, class RRef, class It>
+concept concat-indirectly-readable-impl = // exposition only
+requires (const It it) {
+{ *it } -> convertible_to<Ref>;
+ { ranges::iter_move(it) } -> convertible_to<RRef>;
+ };
+
+template <class... Rs>
+concept concat-indirectly-readable = // exposition only
+<concat-reference-t<Rs...>&&,
+ common_reference_with<Rs...>&> &&
+ concat-value-t<concat-reference-t<Rs...>&&,
+ common_reference_with<Rs...>&&> &&
+ concat-rvalue-reference-t<concat-rvalue-reference-t<Rs...>&&,
+ common_reference_with<Rs...> const&> &&
+ concat-value-t(concat-indirectly-readable-impl<concat-reference-t<Rs...>,
+ <Rs...>,
+ concat-rvalue-reference-t<Rs>> && ...); iterator_t
template <class... Rs>
-concept concatable = see below; // exposition only
template <class... Rs>
+concept concatable = see below; // exposition only
concatable
concept is
equivalent to:template <class... Rs>
-concept concatable = requires { // exposition only
-typename concat-reference-t<Rs...>;
- typename concat-value-t<Rs...>;
- typename concat-rvalue-reference-t<Rs...>;
- } && concat-indirectly-readable<Rs...>;
template <class... Rs>
+concept concatable = requires { // exposition only
+typename concat-reference-t<Rs...>;
+ typename concat-value-t<Rs...>;
+ typename concat-rvalue-reference-t<Rs...>;
+ } && concat-indirectly-readable<Rs...>;
template <bool Const, class... Rs>
-concept concat-is-random-access = see below; // exposition only
template <bool Const, class... Rs>
+concept concat-is-random-access = see below; // exposition only
Fs
be the pack that consists
@@ -1473,13 +1431,13 @@ ?.?.?.2
last, then
concat-is-random-access
is equivalent to:
-template <bool Const, class... Rs>
-concept concat-is-random-access = // exposition only
-<Const, Rs...> &&
- all-random-access(sized_range<maybe-const<Const, Fs>> && ...);
template <bool Const, class... Rs>
+concept concat-is-random-access = // exposition only
+<Const, Rs...> &&
+ all-random-access(common_range<maybe-const<Const, Fs>> && ...);
template <bool Const, class... Rs>
-concept concat-is-bidirectional = see below; // exposition only
template <bool Const, class... Rs>
+concept concat-is-bidirectional = see below; // exposition only
Fs
be the pack that consists
@@ -1487,20 +1445,20 @@ ?.?.?.2
last element, then
concat-is-bidirectional
is equivalent to:
-template <bool Const, class... Rs>
-concept concat-is-bidirectional = // exposition only
-(all-bidirectional<Const, Rs...> && ... && common-arg<maybe-const<Const, Fs>>);
template <bool Const, class... Rs>
+concept concat-is-bidirectional = // exposition only
+(all-bidirectional<Const, Rs...> && ... && common_range<maybe-const<Const, Fs>>);
constexpr explicit concat_view(Views... views);
constexpr explicit concat_view(Views... views);
views_
with
std::move(views)...
.constexpr iterator<false> begin() requires(!(simple-view<Views> && ...));
-constexpr iterator<true> begin() const
-requires((range<const Views> && ...) && concatable<const Views...>);
constexpr iterator<false> begin() requires(!(simple-view<Views> && ...));
+constexpr iterator<true> begin() const
+requires((range<const Views> && ...) && concatable<const Views...>);
?.?.?.2
true
for the const-qualified
overload, and false
otherwise.
Equivalent to:
-<is-const> it(this, in_place_index<0>, ranges::begin(get<0>(views_)));
- iterator.template satisfy<0>();
- itreturn it;
<is-const> it(this, in_place_index<0>, ranges::begin(get<0>(views_)));
+ iterator.template satisfy<0>();
+ itreturn it;
constexpr auto end() requires(!(simple-view<Views> && ...));
-constexpr auto end() const requires(range<const Views>&&...);
constexpr auto end() requires(!(simple-view<Views> && ...));
+constexpr auto end() const requires(range<const Views>&&...);
?.?.?.2
const-qualified overload, and the last element of the pack
Views...
otherwise. Equivalent
to:
-if constexpr (common_range<last-view>) {
-constexpr auto N = sizeof...(Views);
- return iterator<is-const>(this, in_place_index<N - 1>,
- ::end(get<N - 1>(views_)));
- ranges} else {
-return default_sentinel;
- }
if constexpr (common_range<last-view>) {
+constexpr auto N = sizeof...(Views);
+ return iterator<is-const>(this, in_place_index<N - 1>,
+ ::end(get<N - 1>(views_)));
+ ranges} else {
+return default_sentinel;
+ }
constexpr auto size() requires(sized_range<Views>&&...);
-constexpr auto size() const requires(sized_range<const Views>&&...);
constexpr auto size() requires(sized_range<Views>&&...);
+constexpr auto size() const requires(sized_range<const Views>&&...);
return apply(
-[](auto... sizes) {
- using CT = make-unsigned-like-t<common_type_t<decltype(sizes)...>>;
- return (CT(sizes) + ...);
- },
- (ranges::size, views_)); tuple-transform
return apply(
+[](auto... sizes) {
+ using CT = make-unsigned-like-t<common_type_t<decltype(sizes)...>>;
+ return (CT(sizes) + ...);
+ },
+ (ranges::size, views_)); tuple-transform
?.?.?.3 Class
concat_view::iterator [range.concat.iterator]
-namespace std::ranges{
-
-template <input_range... Views>
- requires (view<Views> && ...) && (sizeof...(Views) > 0) &&
- <Views...>
- concatabletemplate <bool Const>
- class concat_view<Views...>::iterator {
-
- public:
- using iterator_category = see below; // not always present.
- using iterator_concept = see below;
- using value_type = concat-value-t<maybe-const<Const, Views>...>;
- using difference_type = common_type_t<range_difference_t<maybe-const<Const, Views>>...>;
-
-private:
- using base-iter = // exposition only
- <iterator_t<maybe-const<Const, Views>>...>;
- variant
- <Const, concat_view>* parent_ = nullptr; // exposition only
- maybe-const// exposition only
- base-iter it_;
-template <std::size_t N>
- constexpr void satisfy(); // exposition only
-
-template <std::size_t N>
- constexpr void prev(); // exposition only
-
-template <std::size_t N>
- constexpr void advance-fwd(difference_type offset, difference_type steps); // exposition only
-
-template <std::size_t N>
- constexpr void advance-bwd(difference_type offset, difference_type steps); // exposition only
-
-template <class... Args>
- explicit constexpr iterator(maybe-const<Const, concat_view>* parent, Args&&... args)
- requires constructible_from<base-iter, Args&&...>; // exposition only
-
-public:
-
-() = default;
- iterator
-constexpr iterator(iterator<!Const> i)
- requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
-
-constexpr decltype(auto) operator*() const;
-
-constexpr iterator& operator++();
-
-constexpr void operator++(int);
-
-constexpr iterator operator++(int)
- requires all-forward<Const, Views...>;
-
- constexpr iterator& operator--()
- requires concat-is-bidirectional<Const, Views...>;
-
-constexpr iterator operator--(int)
- requires concat-is-bidirectional<Const, Views...>;
-
-constexpr iterator& operator+=(difference_type n)
- requires concat-is-random-access<Const, Views...>;
-
-constexpr iterator& operator-=(difference_type n)
- requires concat-is-random-access<Const, Views...>;
-
-constexpr decltype(auto) operator[](difference_type n) const
- requires concat-is-random-access<Const, Views...>;
-
-friend constexpr bool operator==(const iterator& x, const iterator& y)
- requires(equality_comparable<iterator_t<maybe-const<Const, Views>>>&&...);
-
-friend constexpr bool operator==(const iterator& it, default_sentinel_t);
-
-friend constexpr bool operator<(const iterator& x, const iterator& y)
- requires all-random-access<Const, Views...>;
-
-friend constexpr bool operator>(const iterator& x, const iterator& y)
- requires all-random-access<Const, Views...>;
-
-friend constexpr bool operator<=(const iterator& x, const iterator& y)
- requires all-random-access<Const, Views...>;
-
-friend constexpr bool operator>=(const iterator& x, const iterator& y)
- requires all-random-access<Const, Views...>;
-
-friend constexpr auto operator<=>(const iterator& x, const iterator& y)
- requires (all-random-access<Const, Views...> &&
- (three_way_comparable<maybe-const<Const, Views>> &&...));
-
-friend constexpr iterator operator+(const iterator& it, difference_type n)
- requires concat-is-random-access<Const, Views...>;
-
-friend constexpr iterator operator+(difference_type n, const iterator& it)
- requires concat-is-random-access<Const, Views...>;
-
-friend constexpr iterator operator-(const iterator& it, difference_type n)
- requires concat-is-random-access<Const, Views...>;
-
-friend constexpr difference_type operator-(const iterator& x, const iterator& y)
- requires concat-is-random-access<Const, Views...>;
-
-friend constexpr difference_type operator-(const iterator& x, default_sentinel_t)
- requires see below;
-
-friend constexpr difference_type operator-(default_sentinel_t, const iterator& x)
- requires see below;
-
-friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below);
-
-friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below)
- requires see below;
- };
-
-}
namespace std::ranges{
+
+template <input_range... Views>
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) &&
+ <Views...>
+ concatabletemplate <bool Const>
+ class concat_view<Views...>::iterator {
+
+ public:
+ using iterator_category = see below; // not always present.
+ using iterator_concept = see below;
+ using value_type = concat-value-t<maybe-const<Const, Views>...>;
+ using difference_type = common_type_t<range_difference_t<maybe-const<Const, Views>>...>;
+
+private:
+ using base-iter = // exposition only
+ <iterator_t<maybe-const<Const, Views>>...>;
+ variant
+ <Const, concat_view>* parent_ = nullptr; // exposition only
+ maybe-const// exposition only
+ base-iter it_;
+template <std::size_t N>
+ constexpr void satisfy(); // exposition only
+
+template <std::size_t N>
+ constexpr void prev(); // exposition only
+
+template <std::size_t N>
+ constexpr void advance-fwd(difference_type offset, difference_type steps); // exposition only
+
+template <std::size_t N>
+ constexpr void advance-bwd(difference_type offset, difference_type steps); // exposition only
+
+template <class... Args>
+ explicit constexpr iterator(maybe-const<Const, concat_view>* parent, Args&&... args)
+ requires constructible_from<base-iter, Args&&...>; // exposition only
+
+public:
+
+() = default;
+ iterator
+constexpr iterator(iterator<!Const> i)
+ requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
+
+constexpr decltype(auto) operator*() const;
+
+constexpr iterator& operator++();
+
+constexpr void operator++(int);
+
+constexpr iterator operator++(int)
+ requires all-forward<Const, Views...>;
+
+ constexpr iterator& operator--()
+ requires concat-is-bidirectional<Const, Views...>;
+
+constexpr iterator operator--(int)
+ requires concat-is-bidirectional<Const, Views...>;
+
+constexpr iterator& operator+=(difference_type n)
+ requires concat-is-random-access<Const, Views...>;
+
+constexpr iterator& operator-=(difference_type n)
+ requires concat-is-random-access<Const, Views...>;
+
+constexpr decltype(auto) operator[](difference_type n) const
+ requires concat-is-random-access<Const, Views...>;
+
+friend constexpr bool operator==(const iterator& x, const iterator& y)
+ requires(equality_comparable<iterator_t<maybe-const<Const, Views>>>&&...);
+
+friend constexpr bool operator==(const iterator& it, default_sentinel_t);
+
+friend constexpr bool operator<(const iterator& x, const iterator& y)
+ requires all-random-access<Const, Views...>;
+
+friend constexpr bool operator>(const iterator& x, const iterator& y)
+ requires all-random-access<Const, Views...>;
+
+friend constexpr bool operator<=(const iterator& x, const iterator& y)
+ requires all-random-access<Const, Views...>;
+
+friend constexpr bool operator>=(const iterator& x, const iterator& y)
+ requires all-random-access<Const, Views...>;
+
+friend constexpr auto operator<=>(const iterator& x, const iterator& y)
+ requires (all-random-access<Const, Views...> &&
+ (three_way_comparable<maybe-const<Const, Views>> &&...));
+
+friend constexpr iterator operator+(const iterator& it, difference_type n)
+ requires concat-is-random-access<Const, Views...>;
+
+friend constexpr iterator operator+(difference_type n, const iterator& it)
+ requires concat-is-random-access<Const, Views...>;
+
+friend constexpr iterator operator-(const iterator& it, difference_type n)
+ requires concat-is-random-access<Const, Views...>;
+
+friend constexpr difference_type operator-(const iterator& x, const iterator& y)
+ requires concat-is-random-access<Const, Views...>;
+
+friend constexpr difference_type operator-(const iterator& x, default_sentinel_t)
+ requires see below;
+
+friend constexpr difference_type operator-(default_sentinel_t, const iterator& x)
+ requires see below;
+
+friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below);
+
+friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below)
+ requires see below;
+ };
+
+}
iterator::iterator_concept
is defined as follows:?.?.
denotes
input_iterator_tag
.
-template <std::size_t N>
-constexpr void satisfy(); // exposition only
template <std::size_t N>
+constexpr void satisfy(); // exposition only
if constexpr (N < (sizeof...(Views) - 1)) {
-if (get<N>(it_) == ranges::end(get<N>(parent_->views_))) {
- .template emplace<N + 1>(ranges::begin(get<N + 1>(parent_->views_)));
- it_<N + 1>();
- satisfy}
- }
if constexpr (N < (sizeof...(Views) - 1)) {
+if (get<N>(it_) == ranges::end(get<N>(parent_->views_))) {
+ .template emplace<N + 1>(ranges::begin(get<N + 1>(parent_->views_)));
+ it_<N + 1>();
+ satisfy}
+ }
template <std::size_t N>
-constexpr void prev(); // exposition only
template <std::size_t N>
+constexpr void prev(); // exposition only
if constexpr (N == 0) {
---get<0>(it_);
- } else {
-if (get<N>(it_) == ranges::begin(get<N>(parent_->views_))) {
- using prev_view = maybe-const<Const, tuple_element_t<N - 1, tuple<Views...>>>;
- if constexpr (common_range<prev_view>) {
- .template emplace<N - 1>(ranges::end(get<N - 1>(parent_->views_)));
- it_} else {
- .template emplace<N - 1>(
- it_::next(ranges::begin(get<N - 1>(parent_->views_)),
- ranges::size(get<N - 1>(parent_->views_))));
- ranges}
- <N - 1>();
- prev} else {
- --get<N>(it_);
- }
- }
if constexpr (N == 0) {
+--get<0>(it_);
+ } else {
+if (get<N>(it_) == ranges::begin(get<N>(parent_->views_))) {
+ .template emplace<N - 1>(ranges::end(get<N - 1>(parent_->views_)));
+ it_<N - 1>();
+ prev} else {
+ --get<N>(it_);
+ }
+ }
template <std::size_t N>
-constexpr void advance-fwd(difference_type offset, difference_type steps); // exposition only
template <std::size_t N>
+constexpr void advance-fwd(difference_type offset, difference_type steps); // exposition only
using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>;
-if constexpr (N == sizeof...(Views) - 1) {
-<N>(it_) += static_cast<underlying_diff_type>(steps);
- get} else {
-auto n_size = ranges::distance(get<N>(parent_->views_));
- if (offset + steps < n_size) {
- <N>(it_) += static_cast<underlying_diff_type>(steps);
- get} else {
- .template emplace<N + 1>(ranges::begin(get<N + 1>(parent_->views_)));
- it_<N + 1>(0, offset + steps - n_size);
- advance-fwd}
- }
using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>;
+if constexpr (N == sizeof...(Views) - 1) {
+<N>(it_) += static_cast<underlying_diff_type>(steps);
+ get} else {
+auto n_size = ranges::distance(get<N>(parent_->views_));
+ if (offset + steps < n_size) {
+ <N>(it_) += static_cast<underlying_diff_type>(steps);
+ get} else {
+ .template emplace<N + 1>(ranges::begin(get<N + 1>(parent_->views_)));
+ it_<N + 1>(0, offset + steps - n_size);
+ advance-fwd}
+ }
template <std::size_t N>
-constexpr void advance-bwd(difference_type offset, difference_type steps); // exposition only
template <std::size_t N>
+constexpr void advance-bwd(difference_type offset, difference_type steps); // exposition only
using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>;
-if constexpr (N == 0) {
-<N>(it_) -= static_cast<underlying_diff_type>(steps);
- get} else {
-if (offset >= steps) {
- <N>(it_) -= static_cast<underlying_diff_type>(steps);
- get} else {
- auto prev_size = ranges::distance(get<N - 1>(parent_->views_));
- .template emplace<N - 1>(ranges::begin(get<N - 1>(parent_->views_)) + prev_size);
- it_<N - 1>(prev_size, steps - offset);
- advance-bwd}
- }
using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>;
+if constexpr (N == 0) {
+<N>(it_) -= static_cast<underlying_diff_type>(steps);
+ get} else {
+if (offset >= steps) {
+ <N>(it_) -= static_cast<underlying_diff_type>(steps);
+ get} else {
+ auto prev_size = ranges::distance(get<N - 1>(parent_->views_));
+ .template emplace<N - 1>(ranges::end(get<N - 1>(parent_->views_)));
+ it_<N - 1>(prev_size, steps - offset);
+ advance-bwd}
+ }
template <class... Args>
-explicit constexpr iterator(
-<Const, concat_view>* parent,
- maybe-const&&... args)
- Argsrequires constructible_from<base-iter, Args&&...>; // exposition only
template <class... Args>
+explicit constexpr iterator(
+<Const, concat_view>* parent,
+ maybe-const&&... args)
+ Argsrequires constructible_from<base-iter, Args&&...>; // exposition only
?.?.
parent
, and initializes
it_
with std::forward<Args>(args)...
.
constexpr iterator(iterator<!Const> i)
-requires Const &&
- (convertible_to<iterator_t<Views>, iterator_t<const Views>>&&...);
constexpr iterator(iterator<!Const> i)
+requires Const &&
+ (convertible_to<iterator_t<Views>, iterator_t<const Views>>&&...);
?.?.
initializes
it_
with
std::move(i.it_)
.
constexpr decltype(auto) operator*() const;
constexpr decltype(auto) operator*() const;
?.?.
is
false
.
using reference = concat-reference-t<maybe-const<Const, Views>...>;
-return std::visit([](auto&& it) -> reference {
-return *it; }, it_);
using reference = concat-reference-t<maybe-const<Const, Views>...>;
+return std::visit([](auto&& it) -> reference {
+return *it; }, it_);
constexpr iterator& operator++();
constexpr iterator& operator++();
?.?.
Effects: Let
i
be it_.index()
.
Equivalent to:
-++get<i>(it_);
-<i>();
- satisfyreturn *this;
++get<i>(it_);
+<i>();
+ satisfyreturn *this;
constexpr void operator++(int);
constexpr void operator++(int);
constexpr iterator operator++(int)
-requires all-forward<Const, Views...>;
constexpr iterator operator++(int)
+requires all-forward<Const, Views...>;
auto tmp = *this;
-++*this;
-return tmp;
auto tmp = *this;
+++*this;
+return tmp;
constexpr iterator& operator--()
-requires concat-is-bidirectional<Const, Views...>;
constexpr iterator& operator--()
+requires concat-is-bidirectional<Const, Views...>;
?.?.
Effects: Let
i
be it_.index()
.
Equivalent to:
-<i>();
- prevreturn *this;
<i>();
+ prevreturn *this;
constexpr iterator operator--(int)
-requires concat-is-bidirectional<Const, Views...>;
constexpr iterator operator--(int)
+requires concat-is-bidirectional<Const, Views...>;
auto tmp = *this;
---*this;
-return tmp;
auto tmp = *this;
+--*this;
+return tmp;
constexpr iterator& operator+=(difference_type n)
-requires concat-is-random-access<Const, Views...>;
constexpr iterator& operator+=(difference_type n)
+requires concat-is-random-access<Const, Views...>;
?.?.
Effects: Let
i
be it_.index()
.
Equivalent to:
-if(n > 0) {
-<i>(get<i>(it_) - ranges::begin(get<i>(parent_->views_)), n);
- advance-fwd} else if (n < 0) {
-<i>(get<i>(it_) - ranges::begin(get<i>(parent_->views_)), -n);
- advance-bwd}
-return *this;
if(n > 0) {
+<i>(get<i>(it_) - ranges::begin(get<i>(parent_->views_)), n);
+ advance-fwd} else if (n < 0) {
+<i>(get<i>(it_) - ranges::begin(get<i>(parent_->views_)), -n);
+ advance-bwd}
+return *this;
constexpr iterator& operator-=(difference_type n)
-requires concat-is-random-access<Const, Views...>;
constexpr iterator& operator-=(difference_type n)
+requires concat-is-random-access<Const, Views...>;
constexpr decltype(auto) operator[](difference_type n) const
-requires concat-is-random-access<Const, Views...>;
constexpr decltype(auto) operator[](difference_type n) const
+requires concat-is-random-access<Const, Views...>;
friend constexpr bool operator==(const iterator& x, const iterator& y)
-requires(equality_comparable<iterator_t<maybe-const<Const, Views>>>&&...);
friend constexpr bool operator==(const iterator& x, const iterator& y)
+requires(equality_comparable<iterator_t<maybe-const<Const, Views>>>&&...);
x.it_.valueless_by_exception()
@@ -1922,30 +1873,30 @@ ?.?.
are each
false
.
return x.it_ == y.it_;
return x.it_ == y.it_;
friend constexpr bool operator==(const iterator& it, default_sentinel_t);
friend constexpr bool operator==(const iterator& it, default_sentinel_t);
it.it_.valueless_by_exception()
is false
.constexpr auto last_idx = sizeof...(Views) - 1;
-return it.it_.index() == last_idx &&
-<last_idx>(it.it_) == ranges::end(get<last_idx>(it.parent_->views_)); get
constexpr auto last_idx = sizeof...(Views) - 1;
+return it.it_.index() == last_idx &&
+<last_idx>(it.it_) == ranges::end(get<last_idx>(it.parent_->views_)); get
friend constexpr bool operator<(const iterator& x, const iterator& y)
-requires all-random-access<Const, Views...>;
- friend constexpr bool operator>(const iterator& x, const iterator& y)
-requires all-random-access<Const, Views...>;
- friend constexpr bool operator<=(const iterator& x, const iterator& y)
-requires all-random-access<Const, Views...>;
- friend constexpr bool operator>=(const iterator& x, const iterator& y)
-requires all-random-access<Const, Views...>;
- friend constexpr auto operator<=>(const iterator& x, const iterator& y)
-requires (all-random-access<Const, Views...> &&
- (three_way_comparable<maybe-const<Const, Views>> &&...));
friend constexpr bool operator<(const iterator& x, const iterator& y)
+requires all-random-access<Const, Views...>;
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
+requires all-random-access<Const, Views...>;
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
+requires all-random-access<Const, Views...>;
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
+requires all-random-access<Const, Views...>;
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
+requires (all-random-access<Const, Views...> &&
+ (three_way_comparable<maybe-const<Const, Views>> &&...));
x.it_.valueless_by_exception()
@@ -1955,34 +1906,34 @@ ?.?.
op
be the operator.
return x.it_ op y.it_;
return x.it_ op y.it_;
friend constexpr iterator operator+(const iterator& it, difference_type n)
-requires concat-is-random-access<Const, Views...>;
friend constexpr iterator operator+(const iterator& it, difference_type n)
+requires concat-is-random-access<Const, Views...>;
it.it_.valueless_by_exception()
is false
.return iterator{it} += n;
return iterator{it} += n;
friend constexpr iterator operator+(difference_type n, const iterator& it)
-requires concat-is-random-access<Const, Views...>;
friend constexpr iterator operator+(difference_type n, const iterator& it)
+requires concat-is-random-access<Const, Views...>;
friend constexpr iterator operator-(const iterator& it, difference_type n)
-requires concat-is-random-access<Const, Views...>;
friend constexpr iterator operator-(const iterator& it, difference_type n)
+requires concat-is-random-access<Const, Views...>;
friend constexpr difference_type operator-(const iterator& x, const iterator& y)
-requires concat-is-random-access<Const, Views...>;
friend constexpr difference_type operator-(const iterator& x, const iterator& y)
+requires concat-is-random-access<Const, Views...>;
x.it_.valueless_by_exception()
@@ -2004,21 +1955,22 @@ ?.?.
sizes of all the ranges
get<i>(x.parent_->views_)
for every integer iy < i < ix
if there is any, and 0
-otherwise, of type make-unsigned-like-t<common_type_t<range_size_t<maybe-const<Const, Views>>...>>
,
-equivalent to
-return dy + static_cast<difference_type>(s) + dx;
difference_type
, equivalent
+to
+return dy + s + dx;
ix < iy
,
equivalent to:return -(y - x);
return -(y - x);
return get<ix>(x.it_) - get<iy>(y.it_);
return get<ix>(x.it_) - get<iy>(y.it_);
friend constexpr difference_type operator-(const iterator& x, default_sentinel_t)
-requires see below;
friend constexpr difference_type operator-(const iterator& x, default_sentinel_t)
+requires see below;
x.it_.valueless_by_exception()
@@ -2030,52 +1982,53 @@ ?.?.
dx
be ranges::distance(get<ix>(x.it_), ranges::end(get<ix>(x.parent_->views_)))
.
Let s
denote the sum of the
sizes of all the ranges get<i>(x.parent_->views_)
-For every integer ix < i < sizeof...(Views)
+for every integer ix < i < sizeof...(Views)
if there is any, and 0
-otherwise, of type make-unsigned-like-t<common_type_t<range_size_t<maybe-const<Const, Views>>...>>
,
-equivalent to
-return -(dx + static_cast<difference_type>(s));
difference_type
, equivalent
+to
+return -(dx + s);
V
be the
last element of the pack Views
,
the expression in the requires-clause is equivalent to:(concat-is-random-access<Const, Views...> && sized_range<maybe-const<Const, V>>)
(concat-is-random-access<Const, Views...> && common_range<maybe-const<Const, V>>)
friend constexpr difference_type operator-(default_sentinel_t, const iterator& x)
-requires see below;
friend constexpr difference_type operator-(default_sentinel_t, const iterator& x)
+requires see below;
return -(x - default_sentinel);
return -(x - default_sentinel);
V
be the
last element of the pack Views
,
the expression in the requires-clause is equivalent to:(concat-is-random-access<Const, Views...> && sized_range<maybe-const<Const, V>>)
(concat-is-random-access<Const, Views...> && common_range<maybe-const<Const, V>>)
friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below);
friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below);
it.it_.valueless_by_exception()
is false
.return std::visit(
-[](const auto& i) ->
- <maybe-const<Const, Views>...> {
- concat-rvalue-reference-treturn ranges::iter_move(i);
- },
- .it_); it
return std::visit(
+[](const auto& i) ->
+ <maybe-const<Const, Views>...> {
+ concat-rvalue-reference-treturn ranges::iter_move(i);
+ },
+ .it_); it
((is_nothrow_invocable_v<decltype(ranges::iter_move),
-const iterator_t<maybe-const<Const, Views>>&> &&
- <range_rvalue_reference_t<maybe-const<Const, Views>>,
- is_nothrow_convertible_v<range_rvalue_reference_t<
- common_reference_t<Const, Views>>...>>) &&...) maybe-const
((is_nothrow_invocable_v<decltype(ranges::iter_move),
+const iterator_t<maybe-const<Const, Views>>&> &&
+ <range_rvalue_reference_t<maybe-const<Const, Views>>,
+ is_nothrow_convertible_v<range_rvalue_reference_t<
+ common_reference_t<Const, Views>>...>>) &&...) maybe-const
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below)
-requires see below;
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below)
+requires see below;
x.it_.valueless_by_exception()
@@ -2083,26 +2036,26 @@ ?.?.
are each
false
.
::visit(
- std[&](const auto& it1, const auto& it2) {
- if constexpr (is_same_v<decltype(it1), decltype(it2)>) {
- ::iter_swap(it1, it2);
- ranges} else {
- ::swap(*x, *y);
- ranges}
- },
- .it_, y.it_); x
::visit(
+ std[&](const auto& it1, const auto& it2) {
+ if constexpr (is_same_v<decltype(it1), decltype(it2)>) {
+ ::iter_swap(it1, it2);
+ ranges} else {
+ ::swap(*x, *y);
+ ranges}
+ },
+ .it_, y.it_); x
(noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its)))
(noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its)))
its
is a pack of
lvalues of type const iterator_t<maybe-const<Const, Views>>
respectively.<iter_reference_t<iterator>, iter_reference_t<iterator>> &&
- swappable_with(... && indirectly_swappable<iterator_t<maybe-const<Const, Views>>>)
<iter_reference_t<iterator>, iter_reference_t<iterator>> &&
+ swappable_with(... && indirectly_swappable<iterator_t<maybe-const<Const, Views>>>)
5.4 Feature Test Macro
<version> synopsis, with
the value selected by the editor to reflect the date of adoption of this
paper:
#define __cpp_lib_ranges_concat 20XXXXL // also in <ranges>
#define __cpp_lib_ranges_concat 20XXXXL // also in <ranges>