diff --git a/stl/inc/iterator b/stl/inc/iterator index 50075d5bfc..402ed5388a 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -1103,14 +1103,22 @@ concept _Has_forward_category = requires { requires derived_from<_Iter_cat_t<_Iter>, forward_iterator_tag>; }; -template -struct iterator_traits> { - using iterator_concept = conditional_t, forward_iterator_tag, input_iterator_tag>; +template +struct _Common_iterator_category_base {}; + +template + requires is_integral_v> +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 +struct iterator_traits> : _Common_iterator_category_base<_Iter> { + using iterator_concept = conditional_t, 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 diff --git a/tests/std/tests/P0896R4_common_iterator/test.cpp b/tests/std/tests/P0896R4_common_iterator/test.cpp index 959e79fb71..b807dff173 100644 --- a/tests/std/tests/P0896R4_common_iterator/test.cpp +++ b/tests/std/tests/P0896R4_common_iterator/test.cpp @@ -315,6 +315,24 @@ constexpr bool test_lwg_3574() { return true; } +template +concept common_iterator_has_iterator_category = + requires { typename iterator_traits>::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); + static_assert(common_iterator_has_iterator_category); + + using small_unbounded_iota = decltype(views::iota(42)); + static_assert(common_iterator_has_iterator_category, + ranges::sentinel_t>); + + using large_unbounded_iota = decltype(views::iota(42ull)); + static_assert(!common_iterator_has_iterator_category, + ranges::sentinel_t>); +} + // 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 {