Skip to content
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