Skip to content

Commit

Permalink
<ranges>: Fix dispatching for views::counted (#5223)
Browse files Browse the repository at this point in the history
  • Loading branch information
frederick-vs-ja authored Jan 14, 2025
1 parent 22b5573 commit 9ec1309
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 19 deletions.
5 changes: 2 additions & 3 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -4216,12 +4216,11 @@ namespace ranges {
using _Decayed = decay_t<_It>;
_STL_INTERNAL_STATIC_ASSERT(input_or_output_iterator<_Decayed>);
if constexpr (contiguous_iterator<_Decayed>) {
return {_St::_Span,
noexcept(span(_STD to_address(_STD declval<_It>()), iter_difference_t<_Decayed>{}))};
return {_St::_Span, true};
} else if constexpr (random_access_iterator<_Decayed>) {
return {_St::_Subrange,
noexcept(subrange(_STD declval<_It>(), _STD declval<_It>() + iter_difference_t<_Decayed>{}))};
} else if constexpr (constructible_from<_Decayed, _It>) {
} else if constexpr (is_convertible_v<_It, _Decayed>) {
return {_St::_Subrange_counted,
noexcept(subrange(
counted_iterator(_STD declval<_It>(), iter_difference_t<_Decayed>{}), default_sentinel))};
Expand Down
28 changes: 14 additions & 14 deletions tests/std/include/range_algorithm_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,12 @@ namespace test {
requires std::signed_integral<Diff> && requires { typename std::iterator_traits<It>::iterator_category; }
struct redifference_iterator_category_base<Diff, It> {
using iterator_category = std::iterator_traits<It>::iterator_category;
using iterator_concept = decltype([] {
};

template <std::_Signed_integer_like Diff, std::input_iterator It>
class redifference_iterator : public redifference_iterator_category_base<Diff, It> {
public:
using iterator_concept = decltype([] {
if constexpr (std::contiguous_iterator<It>) {
return std::contiguous_iterator_tag{};
} else if constexpr (std::random_access_iterator<It>) {
Expand All @@ -977,13 +982,8 @@ namespace test {
return std::input_iterator_tag{};
}
}());
};

template <std::_Signed_integer_like Diff, std::input_iterator It>
class redifference_iterator : public redifference_iterator_category_base<Diff, It> {
public:
using value_type = std::iter_value_t<It>;
using difference_type = Diff;
using value_type = std::iter_value_t<It>;
using difference_type = Diff;

redifference_iterator() = default;
constexpr explicit redifference_iterator(It it) : i_{std::move(it)} {}
Expand Down Expand Up @@ -1052,22 +1052,22 @@ namespace test {
return i.i_ == j.i_;
}

[[nodiscard]] friend constexpr redifference_iterator operator+(
const redifference_iterator& it, std::same_as<difference_type> auto n)
template <std::same_as<difference_type> I> // TRANSITION, DevCom-10735214, should be abbreviated
[[nodiscard]] friend constexpr redifference_iterator operator+(const redifference_iterator& it, I n)
requires std::random_access_iterator<It>
{
return redifference_iterator{it.i_ + static_cast<std::iter_difference_t<It>>(n)};
}

[[nodiscard]] friend constexpr redifference_iterator operator+(
std::same_as<difference_type> auto n, const redifference_iterator& it)
template <std::same_as<difference_type> I> // TRANSITION, DevCom-10735214, should be abbreviated
[[nodiscard]] friend constexpr redifference_iterator operator+(I n, const redifference_iterator& it)
requires std::random_access_iterator<It>
{
return redifference_iterator{it.i_ + static_cast<std::iter_difference_t<It>>(n)};
}

[[nodiscard]] friend constexpr redifference_iterator operator-(
const redifference_iterator& it, std::same_as<difference_type> auto n)
template <std::same_as<difference_type> I> // TRANSITION, DevCom-10735214, should be abbreviated
[[nodiscard]] friend constexpr redifference_iterator operator-(const redifference_iterator& it, I n)
requires std::random_access_iterator<It>
{
return redifference_iterator{it.i_ - static_cast<std::iter_difference_t<It>>(n)};
Expand Down
44 changes: 42 additions & 2 deletions tests/std/tests/P0896R4_views_counted/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ template <class I>
concept Countable = requires { typename iter_difference_t<remove_cvref_t<I>>; }
&& requires(I&& i, iter_difference_t<remove_cvref_t<I>> n) { views::counted(forward<I>(i), n); };

template <class I>
concept CanConstructCountedSubrange = requires { typename iter_difference_t<remove_cvref_t<I>>; }
&& requires(I&& i, iter_difference_t<remove_cvref_t<I>> n) {
ranges::subrange(counted_iterator(forward<I>(i), n), default_sentinel);
};

template <input_or_output_iterator Iter>
struct convertible_difference {
constexpr convertible_difference(const int _val_) noexcept : _val(_val_) {}
Expand All @@ -31,8 +37,7 @@ struct instantiator {

template <input_or_output_iterator Iter>
static constexpr void call() {
using ranges::contiguous_range, ranges::equal, ranges::iterator_t, ranges::random_access_range, ranges::size,
ranges::subrange;
using ranges::equal, ranges::size, ranges::subrange;
int input[] = {13, 42, 1729, -1, -1};

static_assert(Countable<Iter>);
Expand All @@ -41,6 +46,10 @@ struct instantiator {
auto result = ranges::views::counted(Iter{input}, convertible_difference<Iter>{3});
if constexpr (contiguous_iterator<Iter>) {
static_assert(same_as<decltype(result), span<remove_reference_t<iter_reference_t<Iter>>, dynamic_extent>>);

const test::redifference_iterator<_Signed128, Iter> rediff_it{Iter{input}};
ranges::contiguous_range auto rediff_result = ranges::views::counted(rediff_it, _Signed128{4});
assert(size(rediff_result) == 4);
} else if constexpr (random_access_iterator<Iter>) {
static_assert(same_as<decltype(result), subrange<Iter, Iter>>);
} else {
Expand All @@ -53,6 +62,37 @@ struct instantiator {
}
};

// Also test GH-5183: "<ranges>: views::counted::_Choose() misses difference casting for contiguous_iterator case"
struct ExplicitCopyCtorIter {
using difference_type = int;

ExplicitCopyCtorIter() = default;
ExplicitCopyCtorIter(ExplicitCopyCtorIter&&) = default;
ExplicitCopyCtorIter& operator=(ExplicitCopyCtorIter&&) = default;
explicit ExplicitCopyCtorIter(const ExplicitCopyCtorIter&) = default;
int operator*();
ExplicitCopyCtorIter& operator++();
void operator++(int);
};
static_assert(!Countable<ExplicitCopyCtorIter&>);
static_assert(!CanConstructCountedSubrange<ExplicitCopyCtorIter&>);

struct ImplicitCopyOnlyIter {
using difference_type = int;

ImplicitCopyOnlyIter() = default;
ImplicitCopyOnlyIter(ImplicitCopyOnlyIter&&) = default;
ImplicitCopyOnlyIter& operator=(ImplicitCopyOnlyIter&&) = default;
explicit ImplicitCopyOnlyIter(const ImplicitCopyOnlyIter&) = delete;
template <int = 0>
ImplicitCopyOnlyIter(const ImplicitCopyOnlyIter&);
int operator*();
ImplicitCopyOnlyIter& operator++();
void operator++(int);
};
static_assert(Countable<ImplicitCopyOnlyIter&>);
static_assert(CanConstructCountedSubrange<ImplicitCopyOnlyIter&>);

int main() {
static_assert(with_writable_iterators<instantiator, int>::call());
with_writable_iterators<instantiator, int>::call();
Expand Down

0 comments on commit 9ec1309

Please sign in to comment.