[libcxx-commits] [libcxx] [libc++] Implement LWG4245: Operators that interact with counted_iterator and default_sentinel_t should be noexcept (PR #235445)
R. Aoto via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Oct 25 06:03:55 PDT 2026
https://github.com/aotodev created https://github.com/llvm/llvm-project/pull/235445
Mark `counted_iterator`'s `operator-` overloads and `operator==` taking `default_sentinel_t` as `noexcept`, as required by the resolution of LWG4245. They only read the stored count. Applied as a defect report to every mode where `counted_iterator` exists (C++20 and later).
The existing `minus.default_sentinel.pass.cpp` and `compare.pass.cpp` now check `noexcept` for both argument orders and the rewritten `!=` forms. They fail without the header change and pass in C++20, C++23 and C++26.
Fixes #148226
>From d2628a09305ddd6bf3f0664708e227b32dc1756a Mon Sep 17 00:00:00 2001
From: Aoto <aotodev at gmail.com>
Date: Sat, 24 Oct 2026 19:22:01 +0200
Subject: [PATCH] [libc++] Implement LWG4245: Operators that interact with
counted_iterator and default_sentinel_t should be noexcept
---
libcxx/docs/Status/Cxx26Issues.csv | 2 +-
libcxx/include/__iterator/counted_iterator.h | 6 +++---
.../predef.iterators/counted.iterator/compare.pass.cpp | 7 ++++++-
.../counted.iterator/minus.default_sentinel.pass.cpp | 7 +++++--
4 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 022479ec72eb6b..638f7a4e6ffa15 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -143,7 +143,7 @@
"`LWG4236 <https://wg21.link/LWG4236>`__","``chunk_view::outer-iterator::value_type`` should provide ``reserve_hint``","2025-06 (Sofia)","","","`#148220 <https://github.com/llvm/llvm-project/issues/148220>`__",""
"`LWG4239 <https://wg21.link/LWG4239>`__","``flat_map``'s transparent comparator no longer works for string literals","2025-06 (Sofia)","","","`#148223 <https://github.com/llvm/llvm-project/issues/148223>`__",""
"`LWG4242 <https://wg21.link/LWG4242>`__","``ranges::distance`` does not work with volatile iterators","2025-06 (Sofia)","|Complete|","14","`#148224 <https://github.com/llvm/llvm-project/issues/148224>`__",""
-"`LWG4245 <https://wg21.link/LWG4245>`__","Operators that interact with ``counted_iterator`` and ``default_sentinel_t`` should be ``noexcept``","2025-06 (Sofia)","","","`#148226 <https://github.com/llvm/llvm-project/issues/148226>`__",""
+"`LWG4245 <https://wg21.link/LWG4245>`__","Operators that interact with ``counted_iterator`` and ``default_sentinel_t`` should be ``noexcept``","2025-06 (Sofia)","|Complete|","24","`#148226 <https://github.com/llvm/llvm-project/issues/148226>`__",""
"`LWG4247 <https://wg21.link/LWG4247>`__","Header ``<stdbit.h>`` is not yet freestanding","2025-06 (Sofia)","","","`#148227 <https://github.com/llvm/llvm-project/issues/148227>`__",""
"","","","","","",""
"`LWG2991 <https://wg21.link/LWG2991>`__","``variant copy`` constructor missing ``noexcept(see below)``","2025-11 (Kona)","|Complete|","24","`#171301 <https://github.com/llvm/llvm-project/issues/171301>`__",""
diff --git a/libcxx/include/__iterator/counted_iterator.h b/libcxx/include/__iterator/counted_iterator.h
index 211670d7ad91f1..c2dcdc65766d10 100644
--- a/libcxx/include/__iterator/counted_iterator.h
+++ b/libcxx/include/__iterator/counted_iterator.h
@@ -204,12 +204,12 @@ class counted_iterator
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr iter_difference_t<_Iter>
- operator-(const counted_iterator& __lhs, default_sentinel_t) {
+ operator-(const counted_iterator& __lhs, default_sentinel_t) noexcept {
return -__lhs.__count_;
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr iter_difference_t<_Iter>
- operator-(default_sentinel_t, const counted_iterator& __rhs) {
+ operator-(default_sentinel_t, const counted_iterator& __rhs) noexcept {
return __rhs.__count_;
}
@@ -239,7 +239,7 @@ class counted_iterator
return __lhs.__count_ == __rhs.__count_;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const counted_iterator& __lhs, default_sentinel_t) {
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const counted_iterator& __lhs, default_sentinel_t) noexcept {
return __lhs.__count_ == 0;
}
diff --git a/libcxx/test/std/iterators/predef.iterators/counted.iterator/compare.pass.cpp b/libcxx/test/std/iterators/predef.iterators/counted.iterator/compare.pass.cpp
index eb349557d76cfd..178ece57bce894 100644
--- a/libcxx/test/std/iterators/predef.iterators/counted.iterator/compare.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/counted.iterator/compare.pass.cpp
@@ -12,7 +12,7 @@
// friend constexpr bool operator==(
// const counted_iterator& x, const counted_iterator<I2>& y);
// friend constexpr bool operator==(
-// const counted_iterator& x, default_sentinel_t);
+// const counted_iterator& x, default_sentinel_t) noexcept;
#include <cassert>
#include <iterator>
@@ -77,6 +77,11 @@ constexpr bool test() {
{
std::counted_iterator iter(cpp20_input_iterator<int*>(buffer), 8);
+ static_assert(noexcept(iter == std::default_sentinel));
+ static_assert(noexcept(iter != std::default_sentinel));
+ static_assert(noexcept(std::default_sentinel == iter));
+ static_assert(noexcept(std::default_sentinel != iter));
+
assert(iter != std::default_sentinel);
assert(std::default_sentinel == std::ranges::next(std::move(iter), 8));
}
diff --git a/libcxx/test/std/iterators/predef.iterators/counted.iterator/minus.default_sentinel.pass.cpp b/libcxx/test/std/iterators/predef.iterators/counted.iterator/minus.default_sentinel.pass.cpp
index d972c6feb187d7..eaf2c4195559b0 100644
--- a/libcxx/test/std/iterators/predef.iterators/counted.iterator/minus.default_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/counted.iterator/minus.default_sentinel.pass.cpp
@@ -9,9 +9,9 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// friend constexpr iter_difference_t<I> operator-(
-// const counted_iterator& x, default_sentinel_t);
+// const counted_iterator& x, default_sentinel_t) noexcept;
// friend constexpr iter_difference_t<I> operator-(
-// default_sentinel_t, const counted_iterator& y);
+// default_sentinel_t, const counted_iterator& y) noexcept;
#include <cassert>
#include <iterator>
@@ -30,6 +30,9 @@ constexpr bool test() {
ASSERT_SAME_TYPE(decltype(iter - std::default_sentinel), std::iter_difference_t<int*>);
ASSERT_SAME_TYPE(decltype(std::default_sentinel - iter), std::iter_difference_t<int*>);
+
+ static_assert(noexcept(iter - std::default_sentinel));
+ static_assert(noexcept(std::default_sentinel - iter));
}
{
const std::counted_iterator iter(random_access_iterator<int*>{buffer}, 8);
More information about the libcxx-commits
mailing list