Skip to content

Commit

Permalink
Implement LWG-3749 common_iterator should handle integer-class diff…
Browse files Browse the repository at this point in the history
…erence types (#4190)
  • Loading branch information
frederick-vs-ja committed Nov 17, 2023
1 parent 5abffb6 commit d9d2a91
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
22 changes: 15 additions & 7 deletions stl/inc/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -1103,14 +1103,22 @@ concept _Has_forward_category = requires {
requires derived_from<_Iter_cat_t<_Iter>, forward_iterator_tag>;
};

template <input_iterator _Iter, class _Se>
struct iterator_traits<common_iterator<_Iter, _Se>> {
using iterator_concept = conditional_t<forward_iterator<_Iter>, forward_iterator_tag, input_iterator_tag>;
template <class _Iter>
struct _Common_iterator_category_base {};

template <class _Iter>
requires is_integral_v<iter_difference_t<_Iter>>
struct _Common_iterator_category_base<_Iter> {
using iterator_category = conditional_t<_Has_forward_category<_Iter>, forward_iterator_tag, input_iterator_tag>;
using value_type = iter_value_t<_Iter>;
using difference_type = iter_difference_t<_Iter>;
using pointer = typename _Common_iterator_pointer_type<_Iter, _Se>::pointer;
using reference = iter_reference_t<_Iter>;
};

template <input_iterator _Iter, class _Se>
struct iterator_traits<common_iterator<_Iter, _Se>> : _Common_iterator_category_base<_Iter> {
using iterator_concept = conditional_t<forward_iterator<_Iter>, forward_iterator_tag, input_iterator_tag>;
using value_type = iter_value_t<_Iter>;
using difference_type = iter_difference_t<_Iter>;
using pointer = typename _Common_iterator_pointer_type<_Iter, _Se>::pointer;
using reference = iter_reference_t<_Iter>;
};

template <class _Iter>
Expand Down
18 changes: 18 additions & 0 deletions tests/std/tests/P0896R4_common_iterator/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,24 @@ constexpr bool test_lwg_3574() {
return true;
}

template <class It, class Se>
concept common_iterator_has_iterator_category =
requires { typename iterator_traits<common_iterator<It, Se>>::iterator_category; };

// LWG-3749 common_iterator should handle integer-class difference types
void test_lwg_3749() { // COMPILE-ONLY
static_assert(common_iterator_has_iterator_category<int*, const int*>);
static_assert(common_iterator_has_iterator_category<int*, unreachable_sentinel_t>);

using small_unbounded_iota = decltype(views::iota(42));
static_assert(common_iterator_has_iterator_category<ranges::iterator_t<small_unbounded_iota>,
ranges::sentinel_t<small_unbounded_iota>>);

using large_unbounded_iota = decltype(views::iota(42ull));
static_assert(!common_iterator_has_iterator_category<ranges::iterator_t<large_unbounded_iota>,
ranges::sentinel_t<large_unbounded_iota>>);
}

// Validate that _Variantish works when fed with a non-trivially-destructible type
void test_non_trivially_destructible_type() { // COMPILE-ONLY
struct non_trivially_destructible_input_iterator {
Expand Down

0 comments on commit d9d2a91

Please sign in to comment.