[libcxx-commits] [libcxx] 9d20703 - [libc++] Implement LWG3749: `common_iterator` should handle integer-class difference types (#233606)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 22 22:46:30 PDT 2026


Author: Vishank Singh
Date: 2026-10-23T13:46:26+08:00
New Revision: 9d207030224595de65c0ca54033bd9d71412921c

URL: https://github.com/llvm/llvm-project/commit/9d207030224595de65c0ca54033bd9d71412921c
DIFF: https://github.com/llvm/llvm-project/commit/9d207030224595de65c0ca54033bd9d71412921c.diff

LOG: [libc++] Implement LWG3749: `common_iterator` should handle integer-class difference types (#233606)

Make `iterator_category` of `iterator_traits<common_iterator<I,S>>`
conditionally present only when `iter_difference_t<I>` is an integral
type.

Fixes #105291

Added: 
    

Modified: 
    libcxx/docs/Status/Cxx26Issues.csv
    libcxx/include/__iterator/common_iterator.h
    libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 8666436cc81e9d..022479ec72eb6b 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -21,7 +21,7 @@
 "`LWG3203 <https://wg21.link/LWG3203>`__","``span`` element access invalidation","2023-11 (Kona)","|Nothing To Do|","","`#105288 <https://github.com/llvm/llvm-project/issues/105288>`__",""
 "`LWG3305 <https://wg21.link/LWG3305>`__","``any_cast<void>``","2023-11 (Kona)","|Complete|","18","`#105289 <https://github.com/llvm/llvm-project/issues/105289>`__",""
 "`LWG3431 <https://wg21.link/LWG3431>`__","``<=>`` for containers should require ``three_way_comparable<T>`` instead of ``<=>``","2023-11 (Kona)","","","`#105290 <https://github.com/llvm/llvm-project/issues/105290>`__",""
-"`LWG3749 <https://wg21.link/LWG3749>`__","``common_iterator`` should handle integer-class 
diff erence types","2023-11 (Kona)","","","`#105291 <https://github.com/llvm/llvm-project/issues/105291>`__",""
+"`LWG3749 <https://wg21.link/LWG3749>`__","``common_iterator`` should handle integer-class 
diff erence types","2023-11 (Kona)","|Complete|","24","`#105291 <https://github.com/llvm/llvm-project/issues/105291>`__",""
 "`LWG3809 <https://wg21.link/LWG3809>`__","Is ``std::subtract_with_carry_engine<uint16_t>`` supposed to work","2023-11 (Kona)","","","`#105295 <https://github.com/llvm/llvm-project/issues/105295>`__",""
 "`LWG3892 <https://wg21.link/LWG3892>`__","Incorrect formatting of nested ranges and tuples","2023-11 (Kona)","|Complete|","17","`#105296 <https://github.com/llvm/llvm-project/issues/105296>`__",""
 "`LWG3897 <https://wg21.link/LWG3897>`__","``inout_ptr`` will not update raw pointer to 0","2023-11 (Kona)","|Complete|","19","`#105297 <https://github.com/llvm/llvm-project/issues/105297>`__",""

diff  --git a/libcxx/include/__iterator/common_iterator.h b/libcxx/include/__iterator/common_iterator.h
index b234b3810308fe..02d4cac0e669aa 100644
--- a/libcxx/include/__iterator/common_iterator.h
+++ b/libcxx/include/__iterator/common_iterator.h
@@ -11,6 +11,7 @@
 #define _LIBCPP___ITERATOR_COMMON_ITERATOR_H
 
 #include <__assert>
+#include <__concepts/arithmetic.h>
 #include <__concepts/assignable.h>
 #include <__concepts/constructible.h>
 #include <__concepts/convertible_to.h>
@@ -282,14 +283,22 @@ struct __arrow_type_or_void<_Iter, _Sent> {
   using type _LIBCPP_NODEBUG = decltype(std::declval<const common_iterator<_Iter, _Sent>&>().operator->());
 };
 
-template <input_iterator _Iter, class _Sent>
-struct iterator_traits<common_iterator<_Iter, _Sent>> {
-  using iterator_concept  = _If<forward_iterator<_Iter>, forward_iterator_tag, input_iterator_tag>;
+template <class _Iter>
+struct __common_iterator_category_base {};
+
+template <class _Iter>
+  requires integral<iter_
diff erence_t<_Iter>>
+struct __common_iterator_category_base<_Iter> {
   using iterator_category = _If<__denotes_forward_iter<_Iter>, forward_iterator_tag, input_iterator_tag>;
-  using pointer           = typename __arrow_type_or_void<_Iter, _Sent>::type;
-  using value_type        = iter_value_t<_Iter>;
-  using 
diff erence_type   = iter_
diff erence_t<_Iter>;
-  using reference         = iter_reference_t<_Iter>;
+};
+
+template <input_iterator _Iter, class _Sent>
+struct iterator_traits<common_iterator<_Iter, _Sent>> : __common_iterator_category_base<_Iter> {
+  using iterator_concept = _If<forward_iterator<_Iter>, forward_iterator_tag, input_iterator_tag>;
+  using pointer          = typename __arrow_type_or_void<_Iter, _Sent>::type;
+  using value_type       = iter_value_t<_Iter>;
+  using 
diff erence_type  = iter_
diff erence_t<_Iter>;
+  using reference        = iter_reference_t<_Iter>;
 };
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp
index 48946dbd7e6de6..b698dae65b5410 100644
--- a/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp
@@ -11,9 +11,11 @@
 // template<input_iterator I, class S>
 //   struct iterator_traits<common_iterator<I, S>>;
 
-#include <iterator>
-
+#include <concepts>
 #include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <ranges>
 #include "test_iterators.h"
 #include "test_macros.h"
 #include "types.h"
@@ -30,7 +32,20 @@ struct NonVoidOutputIterator {
     void operator=(int) const;
 };
 
+template <class It, class Se>
+concept has_iterator_category =
+    requires { typename std::iterator_traits<std::common_iterator<It, Se>>::iterator_category; };
+
 void test() {
+  // LWG 3749: common_iterator should handle integer-class 
diff erence types
+  {
+    using WideIota = decltype(std::views::iota(std::uint64_t{0}));
+    using WideIter = std::ranges::iterator_t<WideIota>;
+    using WideSent = std::ranges::sentinel_t<WideIota>;
+
+    constexpr bool is_
diff _integral = std::integral<std::iter_
diff erence_t<WideIter>>;
+    static_assert(has_iterator_category<WideIter, WideSent> == is_
diff _integral);
+  }
   {
     using Iter = simple_iterator<int*>;
     using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;


        


More information about the libcxx-commits mailing list