[libcxx-commits] [libcxx] [libc++] Simplify the implementation of iterator_traits a bit (PR #222297)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Sep 10 06:18:22 PDT 2026
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/222297
>From f42049d01c039a9df113aa04fcb04b26da9c7da3 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 9 Sep 2026 13:01:53 +0200
Subject: [PATCH] [libc++] Simplify the implementation of iterator_traits a bit
---
libcxx/include/__iterator/iterator_traits.h | 133 ++++++--------------
1 file changed, 35 insertions(+), 98 deletions(-)
diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h
index 4327317b23d46..25eff3d954cdb 100644
--- a/libcxx/include/__iterator/iterator_traits.h
+++ b/libcxx/include/__iterator/iterator_traits.h
@@ -37,6 +37,7 @@
#include <__type_traits/remove_const.h>
#include <__type_traits/remove_cv.h>
#include <__type_traits/remove_cvref.h>
+#include <__type_traits/type_identity.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
@@ -123,21 +124,12 @@ concept __cpp17_random_access_iterator =
};
} // namespace __iterator_traits_detail
-template <class _Ip>
-concept __has_member_reference = requires { typename _Ip::reference; };
-
-template <class _Ip>
-concept __has_member_pointer = requires { typename _Ip::pointer; };
-
-template <class _Ip>
-concept __has_member_iterator_category = requires { typename _Ip::iterator_category; };
-
template <class _Ip>
concept __specifies_members = requires {
typename _Ip::value_type;
typename _Ip::difference_type;
- requires __has_member_reference<_Ip>;
- requires __has_member_iterator_category<_Ip>;
+ typename _Ip::reference;
+ typename _Ip::iterator_category;
};
template <class _Tp>
@@ -147,92 +139,34 @@ template <class _Tp>
concept __cpp17_input_iterator_missing_members =
__cpp17_iterator_missing_members<_Tp> && __iterator_traits_detail::__cpp17_input_iterator<_Tp>;
-// Otherwise, `pointer` names `void`.
-template <class>
-struct __iterator_traits_member_pointer_or_arrow_or_void {
- using type _LIBCPP_NODEBUG = void;
-};
-
// [iterator.traits]/3.2.1
-// If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type.
-template <__has_member_pointer _Ip>
-struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> {
- using type _LIBCPP_NODEBUG = typename _Ip::pointer;
-};
-
-// Otherwise, if `decltype(declval<I&>().operator->())` is well-formed, then `pointer` names that
-// type.
-template <class _Ip>
- requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>)
-struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> {
- using type _LIBCPP_NODEBUG = decltype(std::declval<_Ip&>().operator->());
-};
-
-// Otherwise, `reference` names `iter-reference-t<I>`.
-template <class _Ip>
-struct __iterator_traits_member_reference {
- using type _LIBCPP_NODEBUG = iter_reference_t<_Ip>;
-};
-
-// [iterator.traits]/3.2.2
-// If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type.
-template <__has_member_reference _Ip>
-struct __iterator_traits_member_reference<_Ip> {
- using type _LIBCPP_NODEBUG = typename _Ip::reference;
-};
-
-// [iterator.traits]/3.2.3.4
-// input_iterator_tag
-template <class _Ip>
-struct __deduce_iterator_category {
- using type _LIBCPP_NODEBUG = input_iterator_tag;
-};
-
-// [iterator.traits]/3.2.3.1
-// `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise
-template <__iterator_traits_detail::__cpp17_random_access_iterator _Ip>
-struct __deduce_iterator_category<_Ip> {
- using type _LIBCPP_NODEBUG = random_access_iterator_tag;
-};
-
-// [iterator.traits]/3.2.3.2
-// `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise
-template <__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip>
-struct __deduce_iterator_category<_Ip> {
- using type _LIBCPP_NODEBUG = bidirectional_iterator_tag;
-};
-
-// [iterator.traits]/3.2.3.3
-// `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise
-template <__iterator_traits_detail::__cpp17_forward_iterator _Ip>
-struct __deduce_iterator_category<_Ip> {
- using type _LIBCPP_NODEBUG = forward_iterator_tag;
-};
-
-template <class _Ip>
-struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {};
+template <class _Iter>
+using __iterator_traits_member_pointer_or_arrow_or_void_t _LIBCPP_NODEBUG = decltype([]<class _Ip = _Iter> {
+ // If the `qualified-id I::pointer` is valid and denotes a type, `pointer` names that type.
+ if constexpr (requires { typename _Ip::pointer; })
+ return type_identity<_Ip>();
+ // Otherwise, if `decltype(declval<I&>().operator->())` is well-formed, then `pointer` names that type.
+ else if constexpr (requires(_Ip& __iter) { __iter.operator->(); })
+ return type_identity<decltype(std::declval<_Ip&>().operator->())>();
+ // Otherwise, `pointer` names `void`.
+ else
+ return type_identity<void>();
+}())::type;
// [iterator.traits]/3.2.3
-// If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names
-// that type.
-template <__has_member_iterator_category _Ip>
-struct __iterator_traits_iterator_category<_Ip> {
- using type _LIBCPP_NODEBUG = typename _Ip::iterator_category;
-};
-
-// otherwise, it names void.
-template <class>
-struct __iterator_traits_difference_type {
- using type _LIBCPP_NODEBUG = void;
-};
-
-// If the qualified-id `incrementable_traits<I>::difference_type` is valid and denotes a type, then
-// `difference_type` names that type;
-template <class _Ip>
- requires requires { typename incrementable_traits<_Ip>::difference_type; }
-struct __iterator_traits_difference_type<_Ip> {
- using type _LIBCPP_NODEBUG = typename incrementable_traits<_Ip>::difference_type;
-};
+template <class _Iter>
+using __iterator_traits_iterator_category_t _LIBCPP_NODEBUG = decltype([]<class _It = _Iter> {
+ if constexpr (requires { typename _It::iterator_category; })
+ return typename _It::iterator_category();
+ else if constexpr (!__iterator_traits_detail::__cpp17_forward_iterator<_It>)
+ return input_iterator_tag();
+ else if constexpr (!__iterator_traits_detail::__cpp17_bidirectional_iterator<_It>)
+ return forward_iterator_tag();
+ else if constexpr (!__iterator_traits_detail::__cpp17_random_access_iterator<_It>)
+ return bidirectional_iterator_tag();
+ else
+ return random_access_iterator_tag();
+}());
// [iterator.traits]/3.4
// Otherwise, `iterator_traits<I>` has no members by any of the above names.
@@ -242,6 +176,9 @@ struct __iterator_traits {};
template <class _Tp>
using __pointer_member _LIBCPP_NODEBUG = typename _Tp::pointer;
+template <class _Tp>
+using __difference_type_member _LIBCPP_NODEBUG = typename _Tp::difference_type;
+
// [iterator.traits]/3.1
// If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and
// `iterator-category`, then `iterator-traits<I>` has the following publicly accessible members:
@@ -259,11 +196,11 @@ struct __iterator_traits<_Ip> {
// `iterator-traits<I>` has the following publicly accessible members:
template <__cpp17_input_iterator_missing_members _Ip>
struct __iterator_traits<_Ip> {
- using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type;
+ using iterator_category = __iterator_traits_iterator_category_t<_Ip>;
using value_type = typename indirectly_readable_traits<_Ip>::value_type;
using difference_type = typename incrementable_traits<_Ip>::difference_type;
- using pointer = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type;
- using reference = typename __iterator_traits_member_reference<_Ip>::type;
+ using pointer = __iterator_traits_member_pointer_or_arrow_or_void_t<_Ip>;
+ using reference = iter_reference_t<_Ip>;
};
// Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then
@@ -272,7 +209,7 @@ template <__cpp17_iterator_missing_members _Ip>
struct __iterator_traits<_Ip> {
using iterator_category = output_iterator_tag;
using value_type = void;
- using difference_type = typename __iterator_traits_difference_type<_Ip>::type;
+ using difference_type = __detected_or_t<void, __difference_type_member, incrementable_traits<_Ip>>;
using pointer = void;
using reference = void;
};
More information about the libcxx-commits
mailing list