Skip to content

Commit 1dd96bd

Browse files
update operator- and test
1 parent 09e29fc commit 1dd96bd

File tree

2 files changed

+79
-44
lines changed

2 files changed

+79
-44
lines changed

libcxx/include/__ranges/concat_view.h

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,25 @@ class concat_view<_Views...>::__iterator {
264264
}
265265
}
266266

267+
template <typename _Func>
268+
_LIBCPP_HIDE_FROM_ABI constexpr auto __invoke_at_index(_Func&& __func) const {
269+
return [&__func, this]<std::size_t _Is>(this auto&& __self) {
270+
if (_Is == __it_.index()) {
271+
return __func.template operator()<_Is>();
272+
} else if constexpr (_Is + 1 < sizeof...(_Views)) {
273+
return __self.template operator()<_Is + 1>();
274+
}
275+
__builtin_unreachable();
276+
}.template operator()<0>();
277+
}
278+
267279
template <size_t... _Is, typename _Func>
268-
_LIBCPP_HIDE_FROM_ABI constexpr void __apply_at_index(size_t __index, _Func&& __func, index_sequence<_Is...>) {
280+
_LIBCPP_HIDE_FROM_ABI constexpr void __apply_at_index(size_t __index, _Func&& __func, index_sequence<_Is...>) const {
269281
((__index == _Is ? (__func(integral_constant<size_t, _Is>{}), 0) : 0), ...);
270282
}
271283

272284
template <size_t _Idx, typename _Func>
273-
_LIBCPP_HIDE_FROM_ABI constexpr void __apply_at_index(size_t __index, _Func&& __func) {
285+
_LIBCPP_HIDE_FROM_ABI constexpr void __apply_at_index(size_t __index, _Func&& __func) const {
274286
__apply_at_index(__index, std::forward<_Func>(__func), make_index_sequence<_Idx>{});
275287
}
276288

@@ -280,6 +292,7 @@ class concat_view<_Views...>::__iterator {
280292
: __it_(std::forward<_Args>(__args)...), __parent_(__parent) {}
281293

282294
friend class concat_view;
295+
friend class __iterator<!_Const>;
283296

284297
public:
285298
_LIBCPP_HIDE_FROM_ABI __iterator() = default;
@@ -517,35 +530,28 @@ class concat_view<_Views...>::__iterator {
517530
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
518531
!__x.__it_.valueless_by_exception() && !__y.__it_.valueless_by_exception(),
519532
"Trying to subtract two iterators of concat_view where at least one iterator is valueless.");
520-
size_t __ix = __x.__it_.index();
521-
size_t __iy = __y.__it_.index();
522-
523-
if (__ix > __iy) {
524-
__x.__it_.template __apply_at_index<tuple_size_v<decltype(__x.__parent_->__views_)>>(
525-
__ix, [&](auto __index_constant_x) {
526-
constexpr size_t __index_x = __index_constant_x.value;
527-
auto __dx = ranges::distance(
528-
ranges::begin(std::get<__index_x>(__x.__parent_->__views_)), std::get<__index_x>(__x.__it_));
529-
530-
__y.__it_.template __apply_at_index<tuple_size_v<decltype(__y.__parent_->__views_)>>(
531-
__iy, [&](auto __index_constant_y) {
532-
constexpr size_t __index_y = __index_constant_y.value;
533-
auto __dy = ranges::distance(
534-
std::get<__index_y>(__y.__it_), ranges::end(std::get<__index_y>(__y.__parent_->__views_)));
535-
difference_type __s = 0;
536-
for (size_t __idx = __index_y + 1; __idx < __index_x; __idx++) {
537-
__s += ranges::size(std::get<__idx>(__x.__parent_->__views_));
538-
}
539-
return __dy + __s + __dx;
540-
});
541-
});
542-
543-
} else if (__ix < __iy) {
544-
return -(__y - __x);
545-
} else {
546-
__variant_detail::__visitation::__variant::__visit_value(
547-
[&](const auto& __it1, const auto& __it2) { return __it1 - __it2; }, __x.__it_, __y.__it_);
548-
}
533+
return __x.__invoke_at_index([&]<std::size_t __index_x>() -> difference_type {
534+
return __y.__invoke_at_index([&]<std::size_t __index_y>() -> difference_type {
535+
if (__index_x > __index_y) {
536+
auto __dx = ranges::distance(
537+
ranges::begin(std::get<__index_x>(__x.__parent_->__views_)), std::get<__index_x>(__x.__it_));
538+
auto __dy = ranges::distance(
539+
std::get<__index_y>(__y.__it_), ranges::end(std::get<__index_y>(__y.__parent_->__views_)));
540+
difference_type __s = [&]<std::size_t __start, std::size_t __end>(this auto&& self) -> difference_type {
541+
if constexpr (__start < __end) {
542+
return ranges::size(std::get<__start>(__x.__parent_->__views_)) +
543+
self.template operator()<__start + 1, __end>();
544+
}
545+
return 0;
546+
}.template operator()<__index_y + 1, __index_x>();
547+
return __dy + __s + __dx;
548+
} else if (__index_x < __index_y) {
549+
return -(__y - __x);
550+
} else {
551+
return std::get<__index_x>(__x.__it_) - std::get<__index_y>(__y.__it_);
552+
}
553+
});
554+
});
549555
}
550556

551557
_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __it, difference_type __n)
@@ -566,19 +572,17 @@ class concat_view<_Views...>::__iterator {
566572
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
567573
!__x.__it_.valueless_by_exception(),
568574
"Trying to subtract a valuess iterators of concat_view from the default sentinel.");
569-
size_t __ix = __x.__it_.index();
570-
__x.__it_.template __apply_at_index<tuple_size_v<decltype(__x.__parent_->__views_)>>(
571-
__ix, [&](auto __index_constant) {
572-
constexpr size_t __index_x = __index_constant.value;
573-
auto __dx = ranges::distance(ranges::begin(std::get<__index_x>(__x.__parent_->__views_)), __x.__it_);
574-
575-
difference_type __s = 0;
576-
for (size_t __idx = 0; __idx < __index_x; __idx++) {
577-
__s += ranges::size(std::get<__idx>(__x.__parent_->__views_));
578-
}
579-
580-
return -(__dx + __s);
581-
});
575+
__x.__invoke_at_index([&]<std::size_t __index_x>() -> difference_type {
576+
auto __dx = ranges::distance(ranges::begin(std::get<__index_x>(__x.__parent_->__views_)), __x.__it_);
577+
difference_type __s = [&]<std::size_t __start, std::size_t __end>(this auto&& self) -> difference_type {
578+
if constexpr (__start < __end) {
579+
return ranges::size(std::get<__start>(__x.__parent_->__views_)) +
580+
self.template operator()<__start + 1, __end>();
581+
}
582+
return 0;
583+
}.template operator()<0, __index_x>();
584+
return -(__dx + __s);
585+
});
582586
}
583587

584588
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(default_sentinel_t, const __iterator& __x)

libcxx/test/std/ranges/range.adaptors/range.concat/iterator/decrement.pass.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "test_iterators.h"
2020
#include "test_macros.h"
2121
#include "../types.h"
22+
#include <iostream>
2223

2324
constexpr void test() {
2425
// Test with a single satisfied value
@@ -81,6 +82,36 @@ constexpr void test() {
8182
assert(result == view.end());
8283
assert(it == (result - 1));
8384
}
85+
86+
// Test two iterators
87+
{
88+
std::array<int, 5> array1{0, 1};
89+
std::array<int, 5> array2{2, 3};
90+
std::ranges::concat_view view(std::views::all(array1), std::views::all(array2));
91+
auto it1 = view.begin();
92+
it1++;
93+
it1++;
94+
auto it2 = view.begin();
95+
auto res = it1 - it2;
96+
std::cout << res << std::endl;
97+
assert(res == 2);
98+
}
99+
100+
// Test one iterator and one sentinel
101+
{
102+
std::array<int, 5> array1{0, 1};
103+
std::array<int, 5> array2{2, 3};
104+
std::ranges::concat_view view(std::views::all(array1), std::views::all(array2));
105+
auto it1 = view.begin();
106+
it1++;
107+
it1++;
108+
it1++;
109+
it1++;
110+
auto it2 = view.begin();
111+
auto res = it1 - it2;
112+
std::cout << res << std::endl;
113+
assert(res == 4);
114+
}
84115
}
85116

86117
int main(int, char**) {

0 commit comments

Comments
 (0)