libstdc++: Implement new predicate concepts from P1716R3
authorJonathan Wakely <jwakely@redhat.com>
Thu, 14 Nov 2019 16:53:18 +0000 (16:53 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 14 Nov 2019 16:53:18 +0000 (16:53 +0000)
* include/bits/iterator_concepts.h (__iter_concept_impl): Add
comments.
(indirect_relation): Rename to indirect_binary_predicate and adjust
definition as per P1716R3.
(indirect_equivalence_relation): Define.
(indirectly_comparable): Adjust definition.
* include/std/concepts (equivalence_relation): Define.
* testsuite/std/concepts/concepts.callable/relation.cc: Add tests for
equivalence_relation.

From-SVN: r278256

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/iterator_concepts.h
libstdc++-v3/include/std/concepts
libstdc++-v3/testsuite/std/concepts/concepts.callable/relation.cc

index 75f4eeb992dec7adb447ca4caa7089cae32ba99f..3714e74bb2323f1a5a94a65b76ba5bf3018f68b3 100644 (file)
@@ -1,5 +1,15 @@
 2019-11-14  Jonathan Wakely  <jwakely@redhat.com>
 
+       * include/bits/iterator_concepts.h (__iter_concept_impl): Add
+       comments.
+       (indirect_relation): Rename to indirect_binary_predicate and adjust
+       definition as per P1716R3.
+       (indirect_equivalence_relation): Define.
+       (indirectly_comparable): Adjust definition.
+       * include/std/concepts (equivalence_relation): Define.
+       * testsuite/std/concepts/concepts.callable/relation.cc: Add tests for
+       equivalence_relation.
+
        * include/bits/iterator_concepts.h (disable_sized_sentinel): Rename to
        disable_sized_sentinel_for.
        * testsuite/24_iterators/headers/iterator/synopsis_c++20.cc: Adjust.
index 7cc058eb8c929c2cfb1786945a1f52572b7aeddf..90a8bc8071f03bfebeb37103f44a030a9071acb0 100644 (file)
@@ -420,20 +420,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace __detail
   {
     template<typename _Iter>
-      struct __iter_concept_impl
-      { };
+      struct __iter_concept_impl;
 
+    // ITER_CONCEPT(I) is ITER_TRAITS(I)::iterator_concept if that is valid.
     template<typename _Iter>
       requires requires { typename __iter_traits<_Iter>::iterator_concept; }
       struct __iter_concept_impl<_Iter>
       { using type = typename __iter_traits<_Iter>::iterator_concept; };
 
+    // Otherwise, ITER_TRAITS(I)::iterator_category if that is valid.
     template<typename _Iter>
       requires (!requires { typename __iter_traits<_Iter>::iterator_concept; }
          && requires { typename __iter_traits<_Iter>::iterator_category; })
       struct __iter_concept_impl<_Iter>
       { using type = typename __iter_traits<_Iter>::iterator_category; };
 
+    // Otherwise, random_access_tag if iterator_traits<I> is not specialized.
     template<typename _Iter>
       requires (!requires { typename __iter_traits<_Iter>::iterator_concept; }
          && !requires { typename __iter_traits<_Iter>::iterator_category; }
@@ -441,7 +443,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       struct __iter_concept_impl<_Iter>
       { using type = random_access_iterator_tag; };
 
-    // ITER_TRAITS
+    // Otherwise, there is no ITER_CONCEPT(I) type.
+    template<typename _Iter>
+      struct __iter_concept_impl
+      { };
+
+    // ITER_CONCEPT
     template<typename _Iter>
       using __iter_concept = typename __iter_concept_impl<_Iter>::type;
   } // namespace __detail
@@ -615,15 +622,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       && predicate<_Fn&, iter_reference_t<_Iter>>
       && predicate<_Fn&, iter_common_reference_t<_Iter>>;
 
+  template<typename _Fn, typename _I1, typename _I2>
+    concept indirect_binary_predicate = readable<_I1> && readable<_I2>
+      && copy_constructible<_Fn>
+      && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
+      && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
+      && predicate<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
+      && predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
+      && predicate<_Fn&, iter_common_reference_t<_I1>,
+                  iter_common_reference_t<_I2>>;
+
   template<typename _Fn, typename _I1, typename _I2 = _I1>
-    concept indirect_relation = readable<_I1> && readable<_I2>
+    concept indirect_equivalence_relation = readable<_I1> && readable<_I2>
       && copy_constructible<_Fn>
-      && relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
-      && relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
-      && relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
-      && relation<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
-      && relation<_Fn&, iter_common_reference_t<_I1>,
-                 iter_common_reference_t<_I2>>;
+      && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
+      && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
+      && equivalence_relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
+      && equivalence_relation<_Fn&, iter_reference_t<_I1>,
+                             iter_reference_t<_I2>>
+      && equivalence_relation<_Fn&, iter_common_reference_t<_I1>,
+                             iter_common_reference_t<_I2>>;
 
   template<typename _Fn, typename _I1, typename _I2 = _I1>
     concept indirect_strict_weak_order = readable<_I1> && readable<_I2>
@@ -767,7 +785,8 @@ namespace ranges
   template<typename _I1, typename _I2, typename _Rel, typename _P1 = identity,
           typename _P2 = identity>
     concept indirectly_comparable
-      = indirect_relation<_Rel, projected<_I1, _P1>, projected<_I2, _P2>>;
+      = indirect_binary_predicate<_Rel, projected<_I1, _P1>,
+                                 projected<_I2, _P2>>;
 
   /// [alg.req.permutable], concept `permutable`
   template<typename _Iter>
index c4acfd2e212f1830b4e52a46cd06c4565633adcc..e6d405a1bee05dd6297ab1d7b43a02549fffbbb8 100644 (file)
@@ -334,26 +334,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // [concepts.callable], callable concepts
 
-  // [concept.invocable], concept invocable
+  /// [concept.invocable], concept invocable
   template<typename _Fn, typename... _Args>
     concept invocable = is_invocable_v<_Fn, _Args...>;
 
-  // [concept.regularinvocable], concept regular_invocable
+  /// [concept.regularinvocable], concept regular_invocable
   template<typename _Fn, typename... _Args>
     concept regular_invocable = invocable<_Fn, _Args...>;
 
-  // [concept.predicate], concept predicate
+  /// [concept.predicate], concept predicate
   template<typename _Fn, typename... _Args>
     concept predicate = regular_invocable<_Fn, _Args...>
       && boolean<invoke_result_t<_Fn, _Args...>>;
 
-  // [concept.relation], concept relation
+  /// [concept.relation], concept relation
   template<typename _Rel, typename _Tp, typename _Up>
     concept relation
       = predicate<_Rel, _Tp, _Tp> && predicate<_Rel, _Up, _Up>
       && predicate<_Rel, _Tp, _Up> && predicate<_Rel, _Up, _Tp>;
 
-  // [concept.strictweakorder], concept strict_weak_order
+  /// [concept.equiv], concept equivalence_relation
+  template<typename _Rel, typename _Tp, typename _Up>
+    concept equivalence_relation = relation<_Rel, _Tp, _Up>;
+
+  /// [concept.strictweakorder], concept strict_weak_order
   template<typename _Rel, typename _Tp, typename _Up>
     concept strict_weak_order = relation<_Rel, _Tp, _Up>;
 
index 783c3ab9c4aab8d04966cffe87b4be29f54c638c..73ff54bbb6d5a7d52e718fdbafcbf62ebf5b63d4 100644 (file)
@@ -46,3 +46,8 @@ struct F
 static_assert( ! std::relation<F, long, long> );
 static_assert( std::relation<F&, int, int> );
 static_assert( std::relation<const F&, const int, const int> );
+
+// [concept.equiv]
+static_assert( std::equivalence_relation<bool(*)(int, int), short, long> );
+static_assert( ! std::equivalence_relation<F, long, long> );
+static_assert( std::equivalence_relation<const F&, const int, const int> );