{ return __t.operator->(); }
};
- // Used in unevaluated expressions to test for implicit conversion to bool.
- namespace __detail { bool __convbool(bool); }
-
//@{
/**
* @param __x A %reverse_iterator.
* iterators.
*
*/
-#if __cplusplus <= 201703L
+#if __cplusplus <= 201703L || ! defined __cpp_lib_concepts
template<typename _Iterator>
inline _GLIBCXX17_CONSTEXPR bool
operator==(const reverse_iterator<_Iterator>& __x,
{ return !(__x < __y); }
#else // C++20
template<typename _IteratorL, typename _IteratorR>
- constexpr auto
+ constexpr bool
operator==(const reverse_iterator<_IteratorL>& __x,
const reverse_iterator<_IteratorR>& __y)
- -> decltype(__detail::__convbool(__x.base() == __y.base()))
+ requires requires { { __x.base() == __y.base() } -> convertible_to<bool>; }
{ return __x.base() == __y.base(); }
template<typename _IteratorL, typename _IteratorR>
- constexpr auto
+ constexpr bool
operator!=(const reverse_iterator<_IteratorL>& __x,
const reverse_iterator<_IteratorR>& __y)
- -> decltype(__detail::__convbool(__x.base() != __y.base()))
+ requires requires { { __x.base() != __y.base() } -> convertible_to<bool>; }
{ return __x.base() != __y.base(); }
template<typename _IteratorL, typename _IteratorR>
- constexpr auto
+ constexpr bool
operator<(const reverse_iterator<_IteratorL>& __x,
const reverse_iterator<_IteratorR>& __y)
- -> decltype(__detail::__convbool(__x.base() < __y.base()))
- { return __x.base() < __y.base(); }
+ requires requires { { __x.base() > __y.base() } -> convertible_to<bool>; }
+ { return __x.base() > __y.base(); }
template<typename _IteratorL, typename _IteratorR>
- constexpr auto
+ constexpr bool
operator>(const reverse_iterator<_IteratorL>& __x,
const reverse_iterator<_IteratorR>& __y)
- -> decltype(__detail::__convbool(__x.base() > __y.base()))
- { return __x.base() > __y.base(); }
+ requires requires { { __x.base() < __y.base() } -> convertible_to<bool>; }
+ { return __x.base() < __y.base(); }
template<typename _IteratorL, typename _IteratorR>
- constexpr auto
+ constexpr bool
operator<=(const reverse_iterator<_IteratorL>& __x,
const reverse_iterator<_IteratorR>& __y)
- -> decltype(__detail::__convbool(__x.base() <= __y.base()))
- { return __x.base() <= __y.base(); }
+ requires requires { { __x.base() >= __y.base() } -> convertible_to<bool>; }
+ { return __x.base() >= __y.base(); }
template<typename _IteratorL, typename _IteratorR>
- constexpr auto
+ constexpr bool
operator>=(const reverse_iterator<_IteratorL>& __x,
const reverse_iterator<_IteratorR>& __y)
- -> decltype(__detail::__convbool(__x.base() >= __y.base()))
- { return __x.base() >= __y.base(); }
+ requires requires { { __x.base() <= __y.base() } -> convertible_to<bool>; }
+ { return __x.base() <= __y.base(); }
+
+ template<typename _IteratorL,
+ three_way_comparable_with<_IteratorL> _IteratorR>
+ constexpr compare_three_way_result_t<_IteratorL, _IteratorR>
+ operator<=>(const reverse_iterator<_IteratorL>& __x,
+ const reverse_iterator<_IteratorR>& __y)
+ { return __y.base() <=> __x.base(); }
#endif // C++20
//@}
#endif // C++20
};
- // Note: See __normal_iterator operators note from Gaby to understand
- // why there are always 2 versions for most of the move_iterator
- // operators.
template<typename _IteratorL, typename _IteratorR>
inline _GLIBCXX17_CONSTEXPR bool
operator==(const move_iterator<_IteratorL>& __x,
const move_iterator<_IteratorR>& __y)
#if __cplusplus > 201703L && __cpp_lib_concepts
- requires requires { __detail::__convbool(__x.base() == __y.base()); }
+ requires requires { { __x.base() == __y.base() } -> convertible_to<bool>; }
#endif
{ return __x.base() == __y.base(); }
- template<typename _Iterator>
- inline _GLIBCXX17_CONSTEXPR bool
- operator==(const move_iterator<_Iterator>& __x,
- const move_iterator<_Iterator>& __y)
- { return __x.base() == __y.base(); }
-
#if __cpp_lib_three_way_comparison
template<typename _IteratorL,
three_way_comparable_with<_IteratorL> _IteratorR>
operator!=(const move_iterator<_IteratorL>& __x,
const move_iterator<_IteratorR>& __y)
{ return !(__x == __y); }
-
- template<typename _Iterator>
- inline _GLIBCXX17_CONSTEXPR bool
- operator!=(const move_iterator<_Iterator>& __x,
- const move_iterator<_Iterator>& __y)
- { return !(__x == __y); }
#endif
template<typename _IteratorL, typename _IteratorR>
operator<(const move_iterator<_IteratorL>& __x,
const move_iterator<_IteratorR>& __y)
#if __cplusplus > 201703L && __cpp_lib_concepts
- requires requires { __detail::__convbool(__x.base() < __y.base()); }
+ requires requires { { __x.base() < __y.base() } -> convertible_to<bool>; }
#endif
{ return __x.base() < __y.base(); }
- template<typename _Iterator>
- inline _GLIBCXX17_CONSTEXPR bool
- operator<(const move_iterator<_Iterator>& __x,
- const move_iterator<_Iterator>& __y)
- { return __x.base() < __y.base(); }
-
template<typename _IteratorL, typename _IteratorR>
inline _GLIBCXX17_CONSTEXPR bool
operator<=(const move_iterator<_IteratorL>& __x,
const move_iterator<_IteratorR>& __y)
#if __cplusplus > 201703L && __cpp_lib_concepts
- requires requires { __detail::__convbool(__y.base() < __x.base()); }
+ requires requires { { __y.base() < __x.base() } -> convertible_to<bool>; }
#endif
{ return !(__y < __x); }
- template<typename _Iterator>
- inline _GLIBCXX17_CONSTEXPR bool
- operator<=(const move_iterator<_Iterator>& __x,
- const move_iterator<_Iterator>& __y)
- { return !(__y < __x); }
-
template<typename _IteratorL, typename _IteratorR>
inline _GLIBCXX17_CONSTEXPR bool
operator>(const move_iterator<_IteratorL>& __x,
const move_iterator<_IteratorR>& __y)
#if __cplusplus > 201703L && __cpp_lib_concepts
- requires requires { __detail::__convbool(__y.base() < __x.base()); }
+ requires requires { { __y.base() < __x.base() } -> convertible_to<bool>; }
#endif
{ return __y < __x; }
- template<typename _Iterator>
- inline _GLIBCXX17_CONSTEXPR bool
- operator>(const move_iterator<_Iterator>& __x,
- const move_iterator<_Iterator>& __y)
- { return __y < __x; }
-
template<typename _IteratorL, typename _IteratorR>
inline _GLIBCXX17_CONSTEXPR bool
operator>=(const move_iterator<_IteratorL>& __x,
const move_iterator<_IteratorR>& __y)
#if __cplusplus > 201703L && __cpp_lib_concepts
- requires requires { __detail::__convbool(__x.base() < __y.base()); }
+ requires requires { { __x.base() < __y.base() } -> convertible_to<bool>; }
#endif
{ return !(__x < __y); }
+#if ! (__cplusplus > 201703L && __cpp_lib_concepts)
+ // Note: See __normal_iterator operators note from Gaby to understand
+ // why we have these extra overloads for some move_iterator operators.
+
+ // These extra overloads are not needed in C++20, because the ones above
+ // are constrained with a requires-clause and so overload resolution will
+ // prefer them to greedy unconstrained function templates.
+
+ template<typename _Iterator>
+ inline _GLIBCXX17_CONSTEXPR bool
+ operator==(const move_iterator<_Iterator>& __x,
+ const move_iterator<_Iterator>& __y)
+ { return __x.base() == __y.base(); }
+
+ template<typename _Iterator>
+ inline _GLIBCXX17_CONSTEXPR bool
+ operator!=(const move_iterator<_Iterator>& __x,
+ const move_iterator<_Iterator>& __y)
+ { return !(__x == __y); }
+
+ template<typename _Iterator>
+ inline _GLIBCXX17_CONSTEXPR bool
+ operator<(const move_iterator<_Iterator>& __x,
+ const move_iterator<_Iterator>& __y)
+ { return __x.base() < __y.base(); }
+
+ template<typename _Iterator>
+ inline _GLIBCXX17_CONSTEXPR bool
+ operator<=(const move_iterator<_Iterator>& __x,
+ const move_iterator<_Iterator>& __y)
+ { return !(__y < __x); }
+
+ template<typename _Iterator>
+ inline _GLIBCXX17_CONSTEXPR bool
+ operator>(const move_iterator<_Iterator>& __x,
+ const move_iterator<_Iterator>& __y)
+ { return __y < __x; }
+
template<typename _Iterator>
inline _GLIBCXX17_CONSTEXPR bool
operator>=(const move_iterator<_Iterator>& __x,
const move_iterator<_Iterator>& __y)
{ return !(__x < __y); }
+#endif // ! C++20
// DR 685.
template<typename _IteratorL, typename _IteratorR>
bool b0 = l0 == r;
bool b1 = l1 != r;
-bool b2 = l2 < r;
-bool b3 = l3 > r;
-bool b4 = l4 <= r;
-bool b5 = l5 >= r;
+bool b2 = l2 > r;
+bool b3 = l3 < r;
+bool b4 = l4 >= r;
+bool b5 = l5 <= r;
template<int N>
concept has_eq
static_assert( ! has_lt<0> );
static_assert( ! has_lt<1> );
-static_assert( has_lt<2> );
-static_assert( ! has_lt<3> );
+static_assert( ! has_lt<2> );
+static_assert( has_lt<3> );
static_assert( ! has_lt<4> );
static_assert( ! has_lt<5> );
static_assert( ! has_gt<0> );
static_assert( ! has_gt<1> );
-static_assert( ! has_gt<2> );
-static_assert( has_gt<3> );
+static_assert( has_gt<2> );
+static_assert( ! has_gt<3> );
static_assert( ! has_gt<4> );
static_assert( ! has_gt<5> );
static_assert( ! has_le<1> );
static_assert( ! has_le<2> );
static_assert( ! has_le<3> );
-static_assert( has_le<4> );
-static_assert( ! has_le<5> );
+static_assert( ! has_le<4> );
+static_assert( has_le<5> );
static_assert( ! has_ge<0> );
static_assert( ! has_ge<1> );
static_assert( ! has_ge<2> );
static_assert( ! has_ge<3> );
-static_assert( ! has_ge<4> );
-static_assert( has_ge<5> );
+static_assert( has_ge<4> );
+static_assert( ! has_ge<5> );
+
+int arr[3] = { 1, 2, 3 };
+constexpr std::reverse_iterator<int*> rbeg = std::rbegin(arr);
+constexpr std::reverse_iterator<const int*> crbeg = std::crbegin(arr);
+static_assert( rbeg == crbeg );
+static_assert( rbeg <= crbeg );
+static_assert( rbeg >= crbeg );
+static_assert( std::is_eq(rbeg <=> crbeg) );
+constexpr std::reverse_iterator<const int*> crend = std::crend(arr);
+static_assert( rbeg != crend );
+static_assert( rbeg < crend );
+static_assert( crend > rbeg );
+static_assert( rbeg <= crend );
+static_assert( crend >= rbeg );
+static_assert( std::is_lt(rbeg <=> crend) );
+
+#include <testsuite_greedy_ops.h>
+
+// copied from 24_iterators/reverse_iterator/greedy_ops.cc
+void test01()
+{
+ typedef std::reverse_iterator<greedy_ops::X*> iterator_type;
+
+ iterator_type it;
+
+ it == it;
+ it != it;
+ it < it;
+ it <= it;
+ it > it;
+ it >= it;
+#if __cplusplus < 201103L
+ it - it; // See PR libstdc++/71771
+#endif
+ 1 + it;
+ it + 1;
+}