mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 03:47:02 -05:00
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.
This commit is contained in:
committed by
Jonathan Wakely
parent
ef0c4482ca
commit
819deae0a5
@@ -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
|
||||
|
||||
52
libstdc++-v3/testsuite/24_iterators/move_iterator/lwg3736.cc
Normal file
52
libstdc++-v3/testsuite/24_iterators/move_iterator/lwg3736.cc
Normal file
@@ -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>> );
|
||||
Reference in New Issue
Block a user