Skip to content

Commit 4483e87

Browse files
Implement LWG-3717 common_view::end should improve random_access_range case (#3266)
1 parent 7164d1c commit 4483e87

File tree

2 files changed

+122
-2
lines changed

2 files changed

+122
-2
lines changed

stl/inc/ranges

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4824,7 +4824,7 @@ namespace ranges {
48244824

48254825
_NODISCARD constexpr auto end() {
48264826
if constexpr (random_access_range<_Vw> && sized_range<_Vw>) {
4827-
return _RANGES begin(_Base) + _RANGES size(_Base);
4827+
return _RANGES begin(_Base) + _RANGES distance(_Base);
48284828
} else {
48294829
return common_iterator<iterator_t<_Vw>, sentinel_t<_Vw>>{_RANGES end(_Base)};
48304830
}
@@ -4834,7 +4834,7 @@ namespace ranges {
48344834
requires range<const _Vw>
48354835
{
48364836
if constexpr (random_access_range<const _Vw> && sized_range<const _Vw>) {
4837-
return _RANGES begin(_Base) + _RANGES size(_Base);
4837+
return _RANGES begin(_Base) + _RANGES distance(_Base);
48384838
} else {
48394839
return common_iterator<iterator_t<const _Vw>, sentinel_t<const _Vw>>{_RANGES end(_Base)};
48404840
}

tests/std/tests/P0896R4_views_common/test.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,128 @@ struct instantiator {
387387
}
388388
};
389389

390+
template <class T>
391+
struct difference_type_only_iterator {
392+
static_assert(is_object_v<T>);
393+
394+
friend constexpr bool operator==(difference_type_only_iterator, difference_type_only_iterator) = default;
395+
friend constexpr auto operator<=>(difference_type_only_iterator, difference_type_only_iterator) = default;
396+
397+
using iterator_concept = contiguous_iterator_tag;
398+
using value_type = remove_cvref_t<T>;
399+
400+
constexpr T& operator*() const noexcept {
401+
return *ptr_;
402+
}
403+
404+
constexpr T* operator->() const noexcept {
405+
return ptr_;
406+
}
407+
408+
constexpr difference_type_only_iterator& operator++() noexcept {
409+
++ptr_;
410+
return *this;
411+
}
412+
413+
constexpr difference_type_only_iterator operator++(int) noexcept {
414+
auto result = *this;
415+
++*this;
416+
return result;
417+
}
418+
419+
constexpr difference_type_only_iterator& operator--() noexcept {
420+
--ptr_;
421+
return *this;
422+
}
423+
424+
constexpr difference_type_only_iterator operator--(int) noexcept {
425+
auto result = *this;
426+
--*this;
427+
return result;
428+
}
429+
430+
constexpr difference_type_only_iterator& operator+=(same_as<ptrdiff_t> auto n) noexcept {
431+
ptr_ += n;
432+
return *this;
433+
}
434+
435+
constexpr difference_type_only_iterator& operator-=(same_as<ptrdiff_t> auto n) noexcept {
436+
ptr_ -= n;
437+
return *this;
438+
}
439+
440+
friend constexpr difference_type_only_iterator operator+(
441+
difference_type_only_iterator i, same_as<ptrdiff_t> auto n) noexcept {
442+
i += n;
443+
return i;
444+
}
445+
446+
friend constexpr difference_type_only_iterator operator+(
447+
same_as<ptrdiff_t> auto n, difference_type_only_iterator i) noexcept {
448+
i += n;
449+
return i;
450+
}
451+
452+
friend constexpr difference_type_only_iterator operator-(
453+
difference_type_only_iterator i, same_as<ptrdiff_t> auto n) noexcept {
454+
i -= n;
455+
return i;
456+
}
457+
458+
friend constexpr ptrdiff_t operator-(difference_type_only_iterator i, difference_type_only_iterator j) noexcept {
459+
return i.ptr_ - j.ptr_;
460+
}
461+
462+
constexpr T& operator[](same_as<ptrdiff_t> auto n) const noexcept {
463+
return ptr_[n];
464+
}
465+
466+
T* ptr_;
467+
};
468+
469+
template <class T>
470+
struct difference_type_only_sentinel {
471+
static_assert(is_object_v<T>);
472+
473+
friend constexpr bool operator==(difference_type_only_iterator<T> i, difference_type_only_sentinel s) noexcept {
474+
return i.ptr_ == s.ptr_end_;
475+
}
476+
477+
friend constexpr ptrdiff_t operator-(difference_type_only_iterator<T> i, difference_type_only_sentinel s) noexcept {
478+
return i.ptr_ - s.ptr_end_;
479+
}
480+
481+
friend constexpr ptrdiff_t operator-(difference_type_only_sentinel s, difference_type_only_iterator<T> i) noexcept {
482+
return s.ptr_end_ - i.ptr_;
483+
}
484+
485+
T* ptr_end_;
486+
};
487+
488+
template <class T>
489+
constexpr bool test_lwg3717() {
490+
remove_cv_t<T> x{};
491+
492+
auto cmv_sr = ranges::subrange(difference_type_only_iterator<T>{&x}, difference_type_only_sentinel<T>{&x + 1})
493+
| views::common;
494+
495+
static_assert(ranges::contiguous_range<decltype(cmv_sr)>);
496+
static_assert(ranges::contiguous_range<const decltype(cmv_sr)>);
497+
498+
assert(ranges::end(cmv_sr) == ranges::begin(cmv_sr) + ptrdiff_t{1});
499+
assert(ranges::end(as_const(cmv_sr)) == ranges::begin(as_const(cmv_sr)) + ptrdiff_t{1});
500+
501+
return true;
502+
}
503+
390504
int main() {
391505
// Get full instantiation coverage
392506
static_assert((test_in<instantiator, const int>(), true));
393507
test_in<instantiator, const int>();
508+
509+
static_assert(test_lwg3717<int>());
510+
static_assert(test_lwg3717<const int>());
511+
512+
assert(test_lwg3717<int>());
513+
assert(test_lwg3717<const int>());
394514
}

0 commit comments

Comments
 (0)