diff --git a/libcxx/docs/OneRangesProposalStatus.csv b/libcxx/docs/OneRangesProposalStatus.csv --- a/libcxx/docs/OneRangesProposalStatus.csv +++ b/libcxx/docs/OneRangesProposalStatus.csv @@ -61,7 +61,7 @@ | indirectly_copyable | indirectly_copyable_storable",[iterator.concepts],Zoe Carver,In progress [common.alg.req]: pt. 2,indirectly_swappable,"| [iterator.concepts] -| [iterator.cust.swap]",Louis Dionne,Not started +| [iterator.cust.swap]",Zoe Carver,✅ [common.alg.req]: pt. 3,indirectly_comparable,[projected],Louis Dionne,Not started [common.alg.req]: pt. 4,"| permutable | mergeable diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h --- a/libcxx/include/__iterator/concepts.h +++ b/libcxx/include/__iterator/concepts.h @@ -249,6 +249,8 @@ constructible_from, iter_rvalue_reference_t<_In>> && assignable_from&, iter_rvalue_reference_t<_In>>; +// Note: indirectly_swappable is located in iter_swap.h. + // clang-format on #endif // !defined(_LIBCPP_HAS_NO_RANGES) 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 @@ -85,6 +85,16 @@ } // namespace ranges +template +concept indirectly_swappable = + indirectly_readable<_I1> && indirectly_readable<_I2> && + requires(const _I1 __i1, const _I2 __i2) { + ranges::iter_swap(__i1, __i1); + ranges::iter_swap(__i2, __i2); + ranges::iter_swap(__i1, __i2); + ranges::iter_swap(__i2, __i1); + }; + #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 @@ -132,6 +132,10 @@ template concept indirectly_movable_storable = see below; // since C++20 +// [alg.req.ind.swap], concept indirectly_swappable +template + concept indirectly_swappable = see below; // since C++20 + template struct iterator // deprecated in C++17 diff --git a/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.swap/indirectly_swappable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.swap/indirectly_swappable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.swap/indirectly_swappable.compile.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 + +// template +// concept indirectly_swappable; + +#include + +#include "test_macros.h" + +template +struct PointerTo { + using value_type = ValueType; + T& operator*() const; +}; + +static_assert(std::indirectly_swappable>); +static_assert(std::indirectly_swappable, PointerTo>); + +struct B; + +struct A { + friend void iter_swap(const PointerTo&, const PointerTo&); +}; + +// Is indirectly swappable. +struct B { + friend void iter_swap(const PointerTo&, const PointerTo&); + friend void iter_swap(const PointerTo&, const PointerTo&); + friend void iter_swap(const PointerTo&, const PointerTo&); +}; + +// Valid except ranges::iter_swap(i2, i1). +struct C { + friend void iter_swap(const PointerTo&, const PointerTo&); + friend void iter_swap(const PointerTo&, const PointerTo&); + friend void iter_swap(const PointerTo&, const PointerTo&) = delete; +}; + +// Valid except ranges::iter_swap(i1, i2). +struct D { + friend void iter_swap(const PointerTo&, const PointerTo&); + friend void iter_swap(const PointerTo&, const PointerTo&) = delete; + friend void iter_swap(const PointerTo&, const PointerTo&); +}; + +// Valid except ranges::iter_swap(i2, i2). +struct E { + E operator=(const E&) = delete; + friend void iter_swap(const PointerTo&, const PointerTo&) = delete; + friend void iter_swap(const PointerTo&, const PointerTo&); + friend void iter_swap(const PointerTo&, const PointerTo&); +}; + +struct F { + friend void iter_swap(const PointerTo&, const PointerTo&) = delete; +}; + +// Valid except ranges::iter_swap(i1, i1). +struct G { + friend void iter_swap(const PointerTo&, const PointerTo&); + friend void iter_swap(const PointerTo&, const PointerTo&); + friend void iter_swap(const PointerTo&, const PointerTo&); +}; + + +static_assert( std::indirectly_swappable, PointerTo>); +static_assert(!std::indirectly_swappable, PointerTo>); +static_assert(!std::indirectly_swappable, PointerTo>); +static_assert(!std::indirectly_swappable, PointerTo>); +static_assert(!std::indirectly_swappable, PointerTo>); diff --git a/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.swap/indirectly_swappable.subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.swap/indirectly_swappable.subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/alg.req.ind.swap/indirectly_swappable.subsumption.compile.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 + +// template +// concept indirectly_swappable; + +#include + +#include + +template + requires std::indirectly_readable && std::indirectly_readable +constexpr bool indirectly_swappable_subsumption() { + return false; +} + +template + requires std::indirectly_swappable +constexpr bool indirectly_swappable_subsumption() { + return true; +} + +static_assert(indirectly_swappable_subsumption());