aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2024-09-02 11:29:13 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2024-09-03 16:18:21 +0100
commit819deae0a5bee079a7d5582fafaa098c26144ae8 (patch)
tree09edba824ed1b572a63031652ce85cfa9a32d716
parentef0c4482ca8069fa56e8d359dbdc6168be499f69 (diff)
downloadgcc-819deae0a5bee079a7d5582fafaa098c26144ae8.zip
gcc-819deae0a5bee079a7d5582fafaa098c26144ae8.tar.gz
gcc-819deae0a5bee079a7d5582fafaa098c26144ae8.tar.bz2
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.
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h8
-rw-r--r--libstdc++-v3/testsuite/24_iterators/move_iterator/lwg3736.cc52
2 files changed, 60 insertions, 0 deletions
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index d382305..20c0319 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 0000000..eaf791b
--- /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>> );