diff --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv --- a/libcxx/docs/Status/RangesPaper.csv +++ b/libcxx/docs/Status/RangesPaper.csv @@ -63,7 +63,7 @@ | indirectly_copyable_storable",[iterator.concepts],Zoe Carver,In progress [common.alg.req]: pt. 2,indirectly_swappable,"| [iterator.concepts] | [iterator.cust.swap]",Zoe Carver,✅ -[common.alg.req]: pt. 3,indirectly_comparable,[projected],Louis Dionne,Not started +[common.alg.req]: pt. 3,indirectly_comparable,[projected],Louis Dionne,✅ [common.alg.req]: pt. 4,"| permutable | mergeable | sortable",[iterator.concepts],Unassigned,Not started diff --git a/libcxx/include/__iterator/iter_swap.h b/libcxx/include/__iterator/iter_swap.h --- a/libcxx/include/__iterator/iter_swap.h +++ b/libcxx/include/__iterator/iter_swap.h @@ -10,9 +10,11 @@ #define _LIBCPP___ITERATOR_ITER_SWAP_H #include <__config> +#include <__functional/identity.h> #include <__iterator/concepts.h> #include <__iterator/iter_move.h> #include <__iterator/iterator_traits.h> +#include <__iterator/projected.h> #include <__iterator/readable_traits.h> #include <__ranges/access.h> #include <__utility/forward.h> @@ -97,6 +99,9 @@ ranges::iter_swap(__i2, __i1); }; +template +concept indirectly_comparable = indirect_binary_predicate<_Rp, projected<_I1, _P1>, projected<_I2, _P2>>; + #endif // !defined(_LIBCPP_HAS_NO_RANGES) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -140,6 +140,11 @@ template concept indirectly_swappable = see below; // since C++20 +template + concept indirectly_­comparable = + indirect_­binary_­predicate, projected>; // since C++20 + template S> requires (!same_as && copyable) class common_iterator; // since C++20 diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept indirectly_­comparable; + +#include +#include + +#include "__iterator/readable_traits.h" +#include "indirectly_readable.h" +#include "test_iterators.h" + +struct Token1 { + int i; +}; +struct Token2 { + int i; +}; +using It1 = IndirectlyReadable; +using It2 = IndirectlyReadable; + +struct GetI { + template + int&& operator()(IHolder&& holder) const noexcept { + return holder.i; + } +}; + +template +struct GoodPredicate { + bool operator()(std::iter_value_t&, std::iter_value_t&) const; + bool operator()(std::iter_value_t&, std::iter_reference_t) const; + bool operator()(std::iter_reference_t, std::iter_value_t&) const; + bool operator()(std::iter_reference_t, std::iter_reference_t) const; + bool operator()(std::iter_common_reference_t, std::iter_common_reference_t) const; +}; + +struct IntPredicate { + bool operator()(int, int) const; +}; + +struct NotPredicate {}; +struct NotIt {}; +static_assert(std::indirectly_comparable>); +static_assert(!std::indirectly_comparable>); +static_assert(!std::indirectly_comparable); +static_assert(std::indirectly_comparable);