https://gcc.gnu.org/g:819deae0a5bee079a7d5582fafaa098c26144ae8

commit r15-3423-g819deae0a5bee079a7d5582fafaa098c26144ae8
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Mon Sep 2 11:29:13 2024 +0100

    libstdc++: Specialize std::disable_sized_sentinel_for for 
std::move_iterator [PR116549]
    
    LWG 3736 added a partial specialization of this variable template for
    two std::move_iterator types. This is needed for the case where the
    types satisfy std::sentinel_for and are subtractable, but do not model
    the semantics requirements of std::sized_sentinel_for.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/116549
            * include/bits/stl_iterator.h (disable_sized_sentinel_for):
            Define specialization for two move_iterator types, as per LWG
            3736.
            * testsuite/24_iterators/move_iterator/lwg3736.cc: New test.

Diff:
---
 libstdc++-v3/include/bits/stl_iterator.h           |  8 ++++
 .../24_iterators/move_iterator/lwg3736.cc          | 52 ++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
b/libstdc++-v3/include/bits/stl_iterator.h
index d38230572709..20c0319f3a7a 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -1822,6 +1822,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { return _ReturnType(__i); }
 
 #if __cplusplus > 201703L && __glibcxx_concepts
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 3736.  move_iterator missing disable_sized_sentinel_for specialization
+  template<typename _Iterator1, typename _Iterator2>
+    requires (!sized_sentinel_for<_Iterator1, _Iterator2>)
+    inline constexpr bool
+    disable_sized_sentinel_for<move_iterator<_Iterator1>,
+                              move_iterator<_Iterator2>> = true;
+
   // [iterators.common] Common iterators
 
   namespace __detail
diff --git a/libstdc++-v3/testsuite/24_iterators/move_iterator/lwg3736.cc 
b/libstdc++-v3/testsuite/24_iterators/move_iterator/lwg3736.cc
new file mode 100644
index 000000000000..eaf791b30893
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/move_iterator/lwg3736.cc
@@ -0,0 +1,52 @@
+// { dg-do compile { target c++20 } }
+
+// 3736.  move_iterator missing disable_sized_sentinel_for specialization
+
+#include <iterator>
+
+template<typename Iter> using MoveIter = std::move_iterator<Iter>;
+
+using std::sized_sentinel_for;
+using std::disable_sized_sentinel_for;
+
+// These assertions always passed, even without LWG 3736:
+static_assert(sized_sentinel_for<MoveIter<int*>, MoveIter<int*>>);
+static_assert(sized_sentinel_for<MoveIter<int*>, MoveIter<const int*>>);
+static_assert(not sized_sentinel_for<MoveIter<int*>, MoveIter<long*>>);
+static_assert(not sized_sentinel_for<MoveIter<int*>, std::default_sentinel_t>);
+static_assert(not disable_sized_sentinel_for<MoveIter<int*>, MoveIter<int*>>);
+
+// These types don't satisfy sized_sentinel_for anyway (because the subtraction
+// is ill-formed) but LWG 3736 makes the variable template explicitly false:
+static_assert(disable_sized_sentinel_for<MoveIter<int*>, MoveIter<long*>>);
+
+struct Iter
+{
+  using iterator_category = std::random_access_iterator_tag;
+  using value_type = int;
+  using pointer = int*;
+  using reference = int&;
+  using difference_type = long;
+
+  Iter() = default;
+  Iter& operator++();
+  Iter operator++(int);
+  Iter& operator--();
+  Iter operator--(int);
+  reference operator*() const;
+  pointer operator->() const;
+  Iter& operator+=(difference_type);
+  Iter& operator-=(difference_type);
+  friend Iter operator+(Iter, difference_type);
+  friend Iter operator+(difference_type, Iter);
+  friend Iter operator-(Iter, difference_type);
+  friend difference_type operator-(Iter, Iter);
+  bool operator==(Iter) const;
+};
+
+// Specialize the variable template so that Iter is not its own sized sentinel:
+template<> constexpr bool std::disable_sized_sentinel_for<Iter, Iter> = true;
+static_assert( not sized_sentinel_for<Iter, Iter> );
+
+// LWG 3736 means that affects std::move_iterator<Iter> as well:
+static_assert( not sized_sentinel_for<MoveIter<Iter>, MoveIter<Iter>> );

Reply via email to