[libcxx-commits] [libcxx] [libc++] Implement LWG3749: `common_iterator` should handle integer-class difference types (PR #233606)
Vishank Singh via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Oct 19 15:10:51 PDT 2026
https://github.com/VishankSingh created https://github.com/llvm/llvm-project/pull/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
>From ed4d609121f0c30dee60dfbf2624db9c927989d7 Mon Sep 17 00:00:00 2001
From: vishanksingh <vishanksinghh at gmail.com>
Date: Tue, 20 Oct 2026 03:31:37 +0530
Subject: [PATCH] [libc++] Implement LWG3749: common_iterator should handle
integer-class difference types
Make `iterator_category` of `iterator_traits<common_iterator<I,S>>`
conditionally present only when `iter_difference_t<I>` is an integral type.
Fixes #105291
---
libcxx/docs/Status/Cxx26Issues.csv | 2 +-
libcxx/include/__iterator/common_iterator.h | 23 +++++++++++-----
.../iterators.common/lwg3749.compile.pass.cpp | 27 +++++++++++++++++++
3 files changed, 44 insertions(+), 8 deletions(-)
create mode 100644 libcxx/test/std/iterators/predef.iterators/iterators.common/lwg3749.compile.pass.cpp
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 180d4a4870e7b8..ce3f9fc8b73691 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 difference types","2023-11 (Kona)","","","`#105291 <https://github.com/llvm/llvm-project/issues/105291>`__",""
+"`LWG3749 <https://wg21.link/LWG3749>`__","``common_iterator`` should handle integer-class difference 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_difference_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 difference_type = iter_difference_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 difference_type = iter_difference_t<_Iter>;
+ using reference = iter_reference_t<_Iter>;
};
#endif // _LIBCPP_STD_VER >= 20
diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/lwg3749.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/lwg3749.compile.pass.cpp
new file mode 100644
index 00000000000000..e9a4fd4bd9c1f8
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/lwg3749.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++20
+
+// LWG 3749: common_iterator should handle integer-class difference types
+
+#include <concepts>
+#include <cstdint>
+#include <iterator>
+#include <ranges>
+
+template <class It, class Se>
+concept has_iterator_category =
+ requires { typename std::iterator_traits<std::common_iterator<It, Se>>::iterator_category; };
+
+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_difference_t<WideIter>>;
+static_assert(has_iterator_category<WideIter, WideSent> == is_diff_integral);
More information about the libcxx-commits
mailing list