[libcxx-commits] [libcxx] [libc++] Only allow operations between const and non-const __wrap_iter specializations (PR #215788)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Aug 12 05:24:02 PDT 2026
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/215788
>From 4d106e037b51950fee7433493e07f3bec470c6de Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 12 Aug 2026 14:21:09 +0200
Subject: [PATCH] [libc++] Only allow operations between const and non-const
__wrap_iter specializations
---
libcxx/include/__iterator/wrap_iter.h | 67 +++++++++++++--------------
libcxx/test/support/min_allocator.h | 2 +-
2 files changed, 32 insertions(+), 37 deletions(-)
diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h
index 89ddb9658c697..c3ac3f6fd027d 100644
--- a/libcxx/include/__iterator/wrap_iter.h
+++ b/libcxx/include/__iterator/wrap_iter.h
@@ -12,17 +12,14 @@
#include <__compare/ordering.h>
#include <__compare/three_way_comparable.h>
+#include <__concepts/same_as.h>
#include <__config>
#include <__cstddef/size_t.h>
#include <__iterator/iterator_traits.h>
#include <__memory/pointer_traits.h>
-#include <__type_traits/conjunction.h>
-#include <__type_traits/disjunction.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/integral_constant.h>
-#include <__type_traits/is_convertible.h>
#include <__type_traits/is_same.h>
-#include <__type_traits/make_const_lvalue_ref.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -45,16 +42,15 @@ class _LIBCPP_WARN_UNUSED __wrap_iter {
private:
_Iter __i_;
+ using __mutable_iter _LIBCPP_NODEBUG = __wrap_iter<__rebind_pointer_t<_Iter, value_type> >;
+
public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter() _NOEXCEPT : __i_() {}
- template <class _OtherIter,
- __enable_if_t<
- _And<is_convertible<const _OtherIter&, _Iter>,
- _Or<is_same<reference, __iterator_reference<_OtherIter> >,
- is_same<reference, __make_const_lvalue_ref<__iterator_reference<_OtherIter> > > > >::value,
- int> = 0>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter(const __wrap_iter<_OtherIter>& __u) _NOEXCEPT
+
+ template <class _MutableIter = __mutable_iter, __enable_if_t<!is_same<_MutableIter, __wrap_iter>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter(const __mutable_iter& __u) _NOEXCEPT
: __i_(__u.__i_) {}
+
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT {
return *__i_;
}
@@ -125,9 +121,9 @@ class _LIBCPP_WARN_UNUSED __wrap_iter {
return __x.__i_ == __y.__i_;
}
- template <class _Iter2>
+ template <class _MutableIter = __mutable_iter, __enable_if_t<!is_same<_MutableIter, __wrap_iter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR bool
- operator==(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
+ operator==(const __wrap_iter& __x, const __mutable_iter& __y) _NOEXCEPT {
return __x.__i_ == __y.__i_;
}
@@ -136,9 +132,9 @@ class _LIBCPP_WARN_UNUSED __wrap_iter {
return __x.__i_ < __y.__i_;
}
- template <class _Iter2>
+ template <class _MutableIter = __mutable_iter, __enable_if_t<!is_same<_MutableIter, __wrap_iter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR bool
- operator<(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
+ operator<(const __wrap_iter& __x, const __mutable_iter& __y) _NOEXCEPT {
return __x.__i_ < __y.__i_;
}
@@ -147,9 +143,9 @@ class _LIBCPP_WARN_UNUSED __wrap_iter {
return !(__x == __y);
}
- template <class _Iter2>
+ template <class _MutableIter = __mutable_iter, __enable_if_t<!is_same<_MutableIter, __wrap_iter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR bool
- operator!=(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
+ operator!=(const __wrap_iter& __x, const __mutable_iter& __y) _NOEXCEPT {
return !(__x == __y);
}
@@ -158,9 +154,9 @@ class _LIBCPP_WARN_UNUSED __wrap_iter {
return __y < __x;
}
- template <class _Iter2>
+ template <class _MutableIter = __mutable_iter, __enable_if_t<!is_same<_MutableIter, __wrap_iter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR bool
- operator>(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
+ operator>(const __wrap_iter& __x, const __mutable_iter& __y) _NOEXCEPT {
return __y < __x;
}
@@ -169,9 +165,9 @@ class _LIBCPP_WARN_UNUSED __wrap_iter {
return !(__x < __y);
}
- template <class _Iter2>
+ template <class _MutableIter = __mutable_iter, __enable_if_t<!is_same<_MutableIter, __wrap_iter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR bool
- operator>=(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
+ operator>=(const __wrap_iter& __x, const __mutable_iter& __y) _NOEXCEPT {
return !(__x < __y);
}
@@ -180,22 +176,23 @@ class _LIBCPP_WARN_UNUSED __wrap_iter {
return !(__y < __x);
}
- template <class _Iter2>
+ template <class _MutableIter = __mutable_iter, __enable_if_t<!is_same<_MutableIter, __wrap_iter>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR bool
- operator<=(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
+ operator<=(const __wrap_iter& __x, const __mutable_iter& __y) _NOEXCEPT {
return !(__y < __x);
}
#else
_LIBCPP_HIDE_FROM_ABI friend bool operator==(const __wrap_iter&, const __wrap_iter&) = default;
- template <class _Iter2>
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool
- operator==(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) noexcept {
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __wrap_iter& __x, const __mutable_iter& __y) noexcept
+ requires(!same_as<__wrap_iter, __mutable_iter>)
+ {
return __x.__i_ == __y.__i_;
}
template <class _Iter2>
+ requires same_as<_Iter, _Iter2> || same_as<__wrap_iter<_Iter2>, __mutable_iter>
_LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering
operator<=>(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) noexcept {
if constexpr (three_way_comparable_with<_Iter, _Iter2, strong_ordering>) {
@@ -212,21 +209,19 @@ class _LIBCPP_WARN_UNUSED __wrap_iter {
}
#endif // _LIBCPP_STD_VER >= 20
-#ifndef _LIBCPP_CXX03_LANG
- template <class _Iter2>
- [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR_SINCE_CXX14 auto
- operator-(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT->decltype(__x.__i_ - __y.__i_)
-#else
- template <class _Iter2>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR_SINCE_CXX14
- typename __wrap_iter::difference_type operator-(const __wrap_iter& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
-#endif // C++03
- {
+ difference_type operator-(const __wrap_iter& __x, const __wrap_iter& __y) _NOEXCEPT {
+ return __x.__i_ - __y.__i_;
+ }
+
+ template <class _MutableIter = __mutable_iter, __enable_if_t<!is_same<_MutableIter, __wrap_iter>::value, int> = 0>
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR_SINCE_CXX14 difference_type
+ operator-(const __wrap_iter& __x, const __mutable_iter& __y) _NOEXCEPT {
return __x.__i_ - __y.__i_;
}
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter
- operator+(typename __wrap_iter::difference_type __n, __wrap_iter __x) _NOEXCEPT {
+ operator+(difference_type __n, __wrap_iter __x) _NOEXCEPT {
__x += __n;
return __x;
}
diff --git a/libcxx/test/support/min_allocator.h b/libcxx/test/support/min_allocator.h
index 193fc5b4d81c4..51f3c06ac35f3 100644
--- a/libcxx/test/support/min_allocator.h
+++ b/libcxx/test/support/min_allocator.h
@@ -337,7 +337,7 @@ class min_pointer<const T, ID> {
typedef std::ptrdiff_t difference_type;
typedef const T& reference;
typedef const T* pointer;
- typedef const T value_type;
+ typedef T value_type;
typedef std::random_access_iterator_tag iterator_category;
TEST_CONSTEXPR_CXX14 reference operator*() const { return *ptr_; }
More information about the libcxx-commits
mailing list