Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement LWG-3749 common_iterator should handle integer-class difference types #4190

Merged
merged 1 commit into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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