[libcxx-commits] [libcxx] 6d72280 - [libc++][ranges] Add indirectly_comparable concept

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jan 4 14:42:19 PST 2022


Author: Nikolas Klauser
Date: 2022-01-04T23:40:57+01:00
New Revision: 6d722801d1a2cd1af8e139c8052443feb62c0eae

URL: https://github.com/llvm/llvm-project/commit/6d722801d1a2cd1af8e139c8052443feb62c0eae
DIFF: https://github.com/llvm/llvm-project/commit/6d722801d1a2cd1af8e139c8052443feb62c0eae.diff

LOG: [libc++][ranges] Add indirectly_comparable concept

Add `indirectly_comparable` concept

Reviewed By: Quuxplusone, Mordante, #libc

Spies: mgorny, libcxx-commits

Differential Revision: https://reviews.llvm.org/D116268

Added: 
    libcxx/include/__iterator/indirectly_comparable.h
    libcxx/test/libcxx/diagnostics/detail.headers/iterator/indirectly_comparable.module.verify.cpp
    libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp

Modified: 
    libcxx/docs/Status/RangesPaper.csv
    libcxx/include/CMakeLists.txt
    libcxx/include/iterator
    libcxx/include/module.modulemap

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv
index ed1900bd12441..2c972f27e0047 100644
--- a/libcxx/docs/Status/RangesPaper.csv
+++ b/libcxx/docs/Status/RangesPaper.csv
@@ -63,7 +63,7 @@ Section,Description,Dependencies,Assignee,Complete
 | 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],Nikolas Klauser,✅
 [common.alg.req]: pt. 4,"| permutable
 | mergeable
 | sortable",[iterator.concepts],Unassigned,Not started

diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 180f7d4259cd3..2354244a5f5e6 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -215,6 +215,7 @@ set(files
   __iterator/erase_if_container.h
   __iterator/front_insert_iterator.h
   __iterator/incrementable_traits.h
+  __iterator/indirectly_comparable.h
   __iterator/insert_iterator.h
   __iterator/istream_iterator.h
   __iterator/istreambuf_iterator.h

diff  --git a/libcxx/include/__iterator/indirectly_comparable.h b/libcxx/include/__iterator/indirectly_comparable.h
new file mode 100644
index 0000000000000..3129b2dcf65e5
--- /dev/null
+++ b/libcxx/include/__iterator/indirectly_comparable.h
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ITERATOR_INDIRECTLY_COMPARABLE_H
+#define _LIBCPP___ITERATOR_INDIRECTLY_COMPARABLE_H
+
+#include <__config>
+#include <__functional/identity.h>
+#include <__iterator/concepts.h>
+#include <__iterator/projected.h>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#ifndef _LIBCPP_HAS_NO_RANGES
+
+template <class _I1, class _I2, class _Rp, class _P1 = identity, class _P2 = identity>
+concept indirectly_comparable =
+  indirect_binary_predicate<_Rp, projected<_I1, _P1>, projected<_I2, _P2>>;
+
+#endif // _LIBCPP_HAS_NO_RANGES
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___ITERATOR_INDIRECTLY_COMPARABLE_H

diff  --git a/libcxx/include/iterator b/libcxx/include/iterator
index 4dd9902d79a2c..be223192de2df 100644
--- a/libcxx/include/iterator
+++ b/libcxx/include/iterator
@@ -140,6 +140,11 @@ template<class In, class Out>
 template<class I1, class I2 = I1>
   concept indirectly_swappable = see below;                // since C++20
 
+template<class I1, class I2, class R, class P1 = identity,
+         class P2 = identity>
+  concept indirectly_comparable =
+    indirect_binary_predicate<R, projected<I1, P1>, projected<I2, P2>>; // since C++20
+
 template<input_or_output_iterator I, sentinel_for<I> S>
   requires (!same_as<I, S> && copyable<I>)
 class common_iterator;                                     // since C++20
@@ -593,6 +598,7 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
 #include <__iterator/erase_if_container.h>
 #include <__iterator/front_insert_iterator.h>
 #include <__iterator/incrementable_traits.h>
+#include <__iterator/indirectly_comparable.h>
 #include <__iterator/insert_iterator.h>
 #include <__iterator/istreambuf_iterator.h>
 #include <__iterator/istream_iterator.h>

diff  --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 1dc6db406a742..8eba28b0efb31 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -594,6 +594,7 @@ module std [system] {
       module erase_if_container    { private header "__iterator/erase_if_container.h" }
       module front_insert_iterator { private header "__iterator/front_insert_iterator.h" }
       module incrementable_traits  { private header "__iterator/incrementable_traits.h" }
+      module indirectly_comparable { private header "__iterator/indirectly_comparable.h" }
       module insert_iterator       { private header "__iterator/insert_iterator.h" }
       module istream_iterator      { private header "__iterator/istream_iterator.h" }
       module istreambuf_iterator   { private header "__iterator/istreambuf_iterator.h" }

diff  --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/indirectly_comparable.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/indirectly_comparable.module.verify.cpp
new file mode 100644
index 0000000000000..7115f7241e893
--- /dev/null
+++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/indirectly_comparable.module.verify.cpp
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: modules-build
+
+// WARNING: This test was generated by 'generate_private_header_tests.py'
+// and should not be edited manually.
+
+// expected-error@*:* {{use of private header from outside its module: '__iterator/indirectly_comparable.h'}}
+#include <__iterator/indirectly_comparable.h>

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
index 0000000000000..ff415cc4ea32b
--- /dev/null
+++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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<class I1, class I2, class R, class P1, class P2>
+// concept indirectly_­comparable;
+
+#include <functional>
+#include <iterator>
+#include <type_traits>
+
+struct Deref {
+    int operator()(int*) const;
+};
+
+static_assert(!std::indirectly_comparable<int, int, std::less<int>>);  // not dereferenceable
+static_assert(!std::indirectly_comparable<int*, int*, int>);  // not a predicate
+static_assert( std::indirectly_comparable<int*, int*, std::less<int>>);
+static_assert(!std::indirectly_comparable<int**, int*, std::less<int>>);
+static_assert( std::indirectly_comparable<int**, int*, std::less<int>, Deref>);
+static_assert(!std::indirectly_comparable<int**, int*, std::less<int>, Deref, Deref>);
+static_assert(!std::indirectly_comparable<int**, int*, std::less<int>, std::identity, Deref>);
+static_assert( std::indirectly_comparable<int*, int**, std::less<int>, std::identity, Deref>);
+
+template<class F>
+  requires std::indirectly_comparable<int*, char*, F>
+           && true // This true is an additional atomic constraint as a tie breaker
+constexpr bool subsumes(F) { return true; }
+
+template<class F>
+  requires std::indirect_binary_predicate<F, std::projected<int*, std::identity>, std::projected<char*, std::identity>>
+void subsumes(F);
+
+template<class F>
+  requires std::indirect_binary_predicate<F, std::projected<int*, std::identity>, std::projected<char*, std::identity>>
+           && true // This true is an additional atomic constraint as a tie breaker
+constexpr bool is_subsumed(F) { return true; }
+
+template<class F>
+  requires std::indirectly_comparable<int*, char*, F>
+void is_subsumed(F);
+
+static_assert(subsumes(std::less<int>()));
+static_assert(is_subsumed(std::less<int>()));


        


More information about the libcxx-commits mailing list