diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h --- a/libcxx/include/__iterator/wrap_iter.h +++ b/libcxx/include/__iterator/wrap_iter.h @@ -164,6 +164,13 @@ template friend class _LIBCPP_TEMPLATE_VIS span; }; +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return __x.base() == __y.base(); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -171,6 +178,17 @@ return __x.base() == __y.base(); } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ +#if _LIBCPP_DEBUG_LEVEL == 2 + _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), + "Attempted to compare incomparable iterators"); +#endif + return __x.base() < __y.base(); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -182,6 +200,13 @@ return __x.base() < __y.base(); } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return !(__x == __y); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -189,6 +214,13 @@ return !(__x == __y); } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return __y < __x; +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -196,6 +228,13 @@ return __y < __x; } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return !(__x < __y); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -203,6 +242,13 @@ return !(__x < __y); } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return !(__y < __x); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT diff --git a/libcxx/test/std/containers/iterator.rel_ops.compile.pass.cpp b/libcxx/test/std/containers/iterator.rel_ops.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/iterator.rel_ops.compile.pass.cpp @@ -0,0 +1,150 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Make sure the various container's iterators are not broken by the use of `std::rel_ops`. + +#include // for std::rel_ops + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +#if TEST_STD_VER >= 11 +#include "filesystem_include.h" +#endif + +#if TEST_STD_VER >= 17 +#include +#endif + +#if TEST_STD_VER >= 20 +#include +#endif + +using namespace std::rel_ops; + +template +void test() { + Container c; + typename Container::iterator it = c.begin(); + typename Container::const_iterator cit = c.begin(); + (void)(it == it); + (void)(it != it); + (void)(it == cit); + (void)(it != cit); + (void)(cit == it); + (void)(cit != it); + (void)(cit == cit); + (void)(cit != cit); +} + +template +void test_random_access() { + Container c; + typename Container::iterator it = c.begin(); + typename Container::const_iterator cit = c.begin(); + (void)(it == it); + (void)(it != it); + (void)(it < it); + (void)(it <= it); + (void)(it > it); + (void)(it >= it); + (void)(it == cit); + (void)(it != cit); + (void)(it < cit); + (void)(it <= cit); + (void)(it > cit); + (void)(it >= cit); + (void)(cit == it); + (void)(cit != it); + (void)(cit < it); + (void)(cit <= it); + (void)(cit > it); + (void)(cit >= it); + (void)(cit == cit); + (void)(cit != cit); + (void)(cit < cit); + (void)(cit <= cit); + (void)(cit > cit); + (void)(cit >= cit); + + // Test the other ops too, even though std::rel_ops shouldn't affect them. + + (void)(it - it); + (void)(it - cit); + (void)(cit - it); + (void)(cit - cit); + + (void)(it + 1); + (void)(it - 1); + (void)(1 + it); + + (void)(cit + 1); + (void)(cit - 1); + (void)(1 + cit); +} + +template void test_random_access >(); +template void test_random_access >(); +template void test >(); +template void test >(); +template void test >(); +template void test >(); +template void test >(); +template void test >(); +template void test(); +template void test >(); +template void test >(); +template void test >(); +template void test >(); +template void test_random_access >(); + +#if TEST_STD_VER >= 11 +void test_directory_iterators() { + fs::directory_iterator it; + fs::recursive_directory_iterator rit; + (void)(it == it); + (void)(it != it); + (void)(rit == rit); + (void)(rit != rit); +} + +template void test(); +#endif + +#if TEST_STD_VER >= 17 +template void test_random_access(); +#endif + +#if TEST_STD_VER >= 20 +void test_span() { + std::span::iterator it; // span has no const_iterator + (void)(it == it); + (void)(it != it); + (void)(it < it); + (void)(it <= it); + (void)(it > it); + (void)(it >= it); + + // Test the other ops too, even though std::rel_ops shouldn't affect them. + + (void)(it - it); + (void)(it + 1); + (void)(it - 1); + (void)(1 + it); +} +#endif