diff mbox series

libstdc++: Implement new predicate concepts from P1716R3

Message ID 20191114165256.GA32533@redhat.com
State New
Headers show
Series libstdc++: Implement new predicate concepts from P1716R3 | expand

Commit Message

Jonathan Wakely Nov. 14, 2019, 4:52 p.m. UTC
* 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.

Tested powerpc64le-linux, committed to trunk.
commit 01e0b14116ce56d4327362686334c37272faac43
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Nov 13 22:26:06 2019 +0000

    libstdc++: Implement new predicate concepts from P1716R3
    
            * 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.
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index 7cc058eb8c9..90a8bc8071f 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -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 = _I1>
-    concept indirect_relation = readable<_I1> && readable<_I2>
+  template<typename _Fn, typename _I1, typename _I2>
+    concept indirect_binary_predicate = 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>>;
+      && 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_equivalence_relation = readable<_I1> && readable<_I2>
+      && copy_constructible<_Fn>
+      && 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>
diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts
index c4acfd2e212..e6d405a1bee 100644
--- a/libstdc++-v3/include/std/concepts
+++ b/libstdc++-v3/include/std/concepts
@@ -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>;
 
diff --git a/libstdc++-v3/testsuite/std/concepts/concepts.callable/relation.cc b/libstdc++-v3/testsuite/std/concepts/concepts.callable/relation.cc
index 783c3ab9c4a..73ff54bbb6d 100644
--- a/libstdc++-v3/testsuite/std/concepts/concepts.callable/relation.cc
+++ b/libstdc++-v3/testsuite/std/concepts/concepts.callable/relation.cc
@@ -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> );