[committed] libstdc++: P1964R2 Wording for boolean-testable

Message ID 20200217183352.GA1574923@redhat.com
State New
Headers show
Series
  • [committed] libstdc++: P1964R2 Wording for boolean-testable
Related show

Commit Message

Jonathan Wakely Feb. 17, 2020, 6:33 p.m.
This removes the complicated std::boolean concept, as agreed in Prague.

	* include/bits/ranges_algo.h (__find_fn, __find_first_of_fn)
	(__adjacent_find_fn): Cast result of predicate to bool.
	* include/std/concepts (__boolean): Remove.
	(__detail::__boolean_testable_impl, __detail::__boolean_testable): Add
	new helper concepts.
	(__detail::__weakly_eq_cmp_with, totally_ordered, totally_ordered_with)
	(predicate): Use __boolean_testable instead of boolean.
	* libsupc++/compare (__detail::__partially_ordered, _Synth3way):
	Likewise.

Tested powerpc64le-linux, committed to master.
commit c5e1c1d3aba39e960cc5fb0dcd77e447e5dee7eb
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Feb 17 18:15:00 2020 +0000

    libstdc++: P1964R2 Wording for boolean-testable
    
    This removes the complicated std::boolean concept, as agreed in Prague.
    
            * include/bits/ranges_algo.h (__find_fn, __find_first_of_fn)
            (__adjacent_find_fn): Cast result of predicate to bool.
            * include/std/concepts (__boolean): Remove.
            (__detail::__boolean_testable_impl, __detail::__boolean_testable): Add
            new helper concepts.
            (__detail::__weakly_eq_cmp_with, totally_ordered, totally_ordered_with)
            (predicate): Use __boolean_testable instead of boolean.
            * libsupc++/compare (__detail::__partially_ordered, _Synth3way):
            Likewise.

Comments

Tim Song Feb. 17, 2020, 9:27 p.m. | #1
On Mon, Feb 17, 2020 at 12:34 PM Jonathan Wakely <jwakely@redhat.com> wrote:

> This removes the complicated std::boolean concept, as agreed in Prague.

>

>         * include/bits/ranges_algo.h (__find_fn, __find_first_of_fn)

>         (__adjacent_find_fn): Cast result of predicate to bool.




Um, why? These look fine without the cast. (The WP was doing == false,
which is a different matter.)



>         * include/std/concepts (__boolean): Remove.

>         (__detail::__boolean_testable_impl, __detail::__boolean_testable):

> Add

>         new helper concepts.

>         (__detail::__weakly_eq_cmp_with, totally_ordered,

> totally_ordered_with)

>         (predicate): Use __boolean_testable instead of boolean.

>         * libsupc++/compare (__detail::__partially_ordered, _Synth3way):

>         Likewise.

>

> Tested powerpc64le-linux, committed to master.

>

>
Jonathan Wakely Feb. 18, 2020, 1:49 p.m. | #2
On 17/02/20 22:27 +0100, Tim Song wrote:
>On Mon, Feb 17, 2020 at 12:34 PM Jonathan Wakely <jwakely@redhat.com> wrote:

>

>> This removes the complicated std::boolean concept, as agreed in Prague.

>>

>>         * include/bits/ranges_algo.h (__find_fn, __find_first_of_fn)

>>         (__adjacent_find_fn): Cast result of predicate to bool.

>

>

>

>Um, why? These look fine without the cast. (The WP was doing == false,

>which is a different matter.)


Good point, I'll undo those bits. Thanks.

>>         * include/std/concepts (__boolean): Remove.

>>         (__detail::__boolean_testable_impl, __detail::__boolean_testable):

>> Add

>>         new helper concepts.

>>         (__detail::__weakly_eq_cmp_with, totally_ordered,

>> totally_ordered_with)

>>         (predicate): Use __boolean_testable instead of boolean.

>>         * libsupc++/compare (__detail::__partially_ordered, _Synth3way):

>>         Likewise.

>>

>> Tested powerpc64le-linux, committed to master.

>>

>>

>
Jonathan Wakely Feb. 19, 2020, 10:57 a.m. | #3
On 18/02/20 13:49 +0000, Jonathan Wakely wrote:
>On 17/02/20 22:27 +0100, Tim Song wrote:

>>On Mon, Feb 17, 2020 at 12:34 PM Jonathan Wakely <jwakely@redhat.com> wrote:

>>

>>>This removes the complicated std::boolean concept, as agreed in Prague.

>>>

>>>        * include/bits/ranges_algo.h (__find_fn, __find_first_of_fn)

>>>        (__adjacent_find_fn): Cast result of predicate to bool.

>>

>>

>>

>>Um, why? These look fine without the cast. (The WP was doing == false,

>>which is a different matter.)

>

>Good point, I'll undo those bits. Thanks.


Looks like we have a few other casts to bool that are redundant
post-p1946r2, not just the ones I added.

This removes them, testing it now.
commit a51a8daabd0ae08e2ee33bbc3c5a52cb20ac0eef
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Feb 19 10:40:24 2020 +0000

    libstdc++: Remove redundant bool casts in ranges algorithms
    
    Some of these casts were added by me the other day, but some were
    already present. I think they are all redundant following the
    introduction of the boolean-testable concept in P1964R2.
    
            * include/bits/ranges_algo.h (__find_fn, __find_first_of_fn)
            (__adjacent_find_fn, __remove_if_fn, __remove_copy_if_fn)
            (__unique_fn, __unique_copy_fn): Remove redundant conversions to bool.

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index 31b1bf0d448..a69181e12cb 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -244,7 +244,7 @@ namespace ranges
 		 const _Tp& __value, _Proj __proj = {}) const
       {
 	while (__first != __last
-	    && !(bool)(std::__invoke(__proj, *__first) == __value))
+	    && !(std::__invoke(__proj, *__first) == __value))
 	  ++__first;
 	return __first;
       }
@@ -333,9 +333,9 @@ namespace ranges
       {
 	for (; __first1 != __last1; ++__first1)
 	  for (auto __iter = __first2; __iter != __last2; ++__iter)
-	    if ((bool)std::__invoke(__pred,
-				    std::__invoke(__proj1, *__first1),
-				    std::__invoke(__proj2, *__iter)))
+	    if (std::__invoke(__pred,
+			      std::__invoke(__proj1, *__first1),
+			      std::__invoke(__proj2, *__iter)))
 	      return __first1;
 	return __first1;
       }
@@ -730,9 +730,9 @@ namespace ranges
 	auto __next = __first;
 	for (; ++__next != __last; __first = __next)
 	  {
-	    if ((bool)std::__invoke(__pred,
-				    std::__invoke(__proj, *__first),
-				    std::__invoke(__proj, *__next)))
+	    if (std::__invoke(__pred,
+			      std::__invoke(__proj, *__first),
+			      std::__invoke(__proj, *__next)))
 	      return __first;
 	  }
 	return __next;
@@ -1219,7 +1219,7 @@ namespace ranges
 	auto __result = __first;
 	++__first;
 	for (; __first != __last; ++__first)
-	  if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
+	  if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
 	    {
 	      *__result = std::move(*__first);
 	      ++__result;
@@ -1289,7 +1289,7 @@ namespace ranges
 		 _Pred __pred, _Proj __proj = {}) const
       {
 	for (; __first != __last; ++__first)
-	  if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
+	  if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
 	    {
 	      *__result = *__first;
 	      ++__result;
@@ -1372,9 +1372,9 @@ namespace ranges
 	auto __dest = __first;
 	++__first;
 	while (++__first != __last)
-	  if (!(bool)std::__invoke(__comp,
-				   std::__invoke(__proj, *__dest),
-				   std::__invoke(__proj, *__first)))
+	  if (!std::__invoke(__comp,
+			     std::__invoke(__proj, *__dest),
+			     std::__invoke(__proj, *__first)))
 	    *++__dest = std::move(*__first);
 	return {++__dest, __first};
       }
@@ -1420,9 +1420,9 @@ namespace ranges
 	    auto __next = __first;
 	    *__result = *__next;
 	    while (++__next != __last)
-	      if (!(bool)std::__invoke(__comp,
-				       std::__invoke(__proj, *__first),
-				       std::__invoke(__proj, *__next)))
+	      if (!std::__invoke(__comp,
+				 std::__invoke(__proj, *__first),
+				 std::__invoke(__proj, *__next)))
 		{
 		  __first = __next;
 		  *++__result = *__first;
@@ -1434,9 +1434,9 @@ namespace ranges
 	  {
 	    *__result = *__first;
 	    while (++__first != __last)
-	      if (!(bool)std::__invoke(__comp,
-				       std::__invoke(__proj, *__result),
-				       std::__invoke(__proj, *__first)))
+	      if (!std::__invoke(__comp,
+				 std::__invoke(__proj, *__result),
+				 std::__invoke(__proj, *__first)))
 		  *++__result = *__first;
 	    return {std::move(__first), std::move(++__result)};
 	  }

Patch

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index f3a349ef839..83f295722e9 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -206,7 +206,7 @@  namespace ranges
 		 const _Tp& __value, _Proj __proj = {}) const
       {
 	while (__first != __last
-	    && !(std::__invoke(__proj, *__first) == __value))
+	    && !(bool)(std::__invoke(__proj, *__first) == __value))
 	  ++__first;
 	return __first;
       }
@@ -295,9 +295,9 @@  namespace ranges
       {
 	for (; __first1 != __last1; ++__first1)
 	  for (auto __iter = __first2; __iter != __last2; ++__iter)
-	    if (std::__invoke(__pred,
-			      std::__invoke(__proj1, *__first1),
-			      std::__invoke(__proj2, *__iter)))
+	    if ((bool)std::__invoke(__pred,
+				    std::__invoke(__proj1, *__first1),
+				    std::__invoke(__proj2, *__iter)))
 	      return __first1;
 	return __first1;
       }
@@ -687,9 +687,9 @@  namespace ranges
 	auto __next = __first;
 	for (; ++__next != __last; __first = __next)
 	  {
-	    if (std::__invoke(__pred,
-			      std::__invoke(__proj, *__first),
-			      std::__invoke(__proj, *__next)))
+	    if ((bool)std::__invoke(__pred,
+				    std::__invoke(__proj, *__first),
+				    std::__invoke(__proj, *__next)))
 	      return __first;
 	  }
 	return __next;
diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts
index acc9dd2599d..f3db40b798f 100644
--- a/libstdc++-v3/include/std/concepts
+++ b/libstdc++-v3/include/std/concepts
@@ -259,27 +259,18 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // [concepts.compare], comparison concepts
 
-  /// [concept.boolean], concept boolean
-  template<typename _Bp>
-    concept boolean
-      = movable<remove_cvref_t<_Bp>>
-      && requires(__detail::__cref<_Bp> __b1, __detail::__cref<_Bp> __b2,
-		  const bool __a) {
-	{ __b1 } -> convertible_to<bool>;
-	{ !__b1 } -> convertible_to<bool>;
-	{ __b1 && __b2 } -> same_as<bool>;
-	{ __b1 && __a  } -> same_as<bool>;
-	{ __a  && __b2 } -> same_as<bool>;
-	{ __b1 || __b2 } -> same_as<bool>;
-	{ __b1 || __a  } -> same_as<bool>;
-	{ __a  || __b2 } -> same_as<bool>;
-	{ __b1 == __b2 } -> convertible_to<bool>;
-	{ __b1 == __a  } -> convertible_to<bool>;
-	{ __a  == __b2 } -> convertible_to<bool>;
-	{ __b1 != __b2 } -> convertible_to<bool>;
-	{ __b1 != __a  } -> convertible_to<bool>;
-	{ __a  != __b2 } -> convertible_to<bool>;
-      };
+  // [concept.booleantestable], Boolean testability
+  namespace __detail
+  {
+    template<typename _Tp>
+      concept __boolean_testable_impl = convertible_to<_Tp, bool>;
+
+    template<typename _Tp>
+      concept __boolean_testable
+	= __boolean_testable_impl<_Tp>
+	  && requires(_Tp&& __t)
+	  { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; };
+  } // namespace __detail
 
   // [concept.equalitycomparable], concept equality_comparable
 
@@ -288,10 +279,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     template<typename _Tp, typename _Up>
       concept __weakly_eq_cmp_with
 	= requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) {
-	  { __t == __u } -> boolean;
-	  { __t != __u } -> boolean;
-	  { __u == __t } -> boolean;
-	  { __u != __t } -> boolean;
+	  { __t == __u } -> __boolean_testable;
+	  { __t != __u } -> __boolean_testable;
+	  { __u == __t } -> __boolean_testable;
+	  { __u != __t } -> __boolean_testable;
 	};
   } // namespace __detail
 
@@ -311,10 +302,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     concept totally_ordered
       = equality_comparable<_Tp>
       && requires(__detail::__cref<_Tp> __a, __detail::__cref<_Tp> __b) {
-	{ __a <  __b } -> boolean;
-	{ __a >  __b } -> boolean;
-	{ __a <= __b } -> boolean;
-	{ __a >= __b } -> boolean;
+	{ __a <  __b } -> __detail::__boolean_testable;
+	{ __a >  __b } -> __detail::__boolean_testable;
+	{ __a <= __b } -> __detail::__boolean_testable;
+	{ __a >= __b } -> __detail::__boolean_testable;
       };
 
   template<typename _Tp, typename _Up>
@@ -325,14 +316,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 					    __detail::__cref<_Up>>>
       && equality_comparable_with<_Tp, _Up>
       && requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) {
-	{ __t <  __u } -> boolean;
-	{ __t >  __u } -> boolean;
-	{ __t <= __u } -> boolean;
-	{ __t >= __u } -> boolean;
-	{ __u <  __t } -> boolean;
-	{ __u >  __t } -> boolean;
-	{ __u <= __t } -> boolean;
-	{ __u >= __t } -> boolean;
+	{ __t <  __u } -> __detail::__boolean_testable;
+	{ __t >  __u } -> __detail::__boolean_testable;
+	{ __t <= __u } -> __detail::__boolean_testable;
+	{ __t >= __u } -> __detail::__boolean_testable;
+	{ __u <  __t } -> __detail::__boolean_testable;
+	{ __u >  __t } -> __detail::__boolean_testable;
+	{ __u <= __t } -> __detail::__boolean_testable;
+	{ __u >= __t } -> __detail::__boolean_testable;
       };
 
   template<typename _Tp>
@@ -351,7 +342,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// [concept.predicate], concept predicate
   template<typename _Fn, typename... _Args>
     concept predicate = regular_invocable<_Fn, _Args...>
-      && boolean<invoke_result_t<_Fn, _Args...>>;
+      && __detail::__boolean_testable<invoke_result_t<_Fn, _Args...>>;
 
   /// [concept.relation], concept relation
   template<typename _Rel, typename _Tp, typename _Up>
diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
index b2d64ef74a4..ba7db316486 100644
--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -416,14 +416,14 @@  namespace std
       concept __partially_ordered_with
 	= requires(const remove_reference_t<_Tp>& __t,
 		   const remove_reference_t<_Up>& __u) {
-	  { __t <  __u } -> boolean;
-	  { __t >  __u } -> boolean;
-	  { __t <= __u } -> boolean;
-	  { __t >= __u } -> boolean;
-	  { __u <  __t } -> boolean;
-	  { __u >  __t } -> boolean;
-	  { __u <= __t } -> boolean;
-	  { __u >= __t } -> boolean;
+	  { __t <  __u } -> __boolean_testable;
+	  { __t >  __u } -> __boolean_testable;
+	  { __t <= __u } -> __boolean_testable;
+	  { __t >= __u } -> __boolean_testable;
+	  { __u <  __t } -> __boolean_testable;
+	  { __u >  __t } -> __boolean_testable;
+	  { __u <= __t } -> __boolean_testable;
+	  { __u >= __t } -> __boolean_testable;
 	};
   } // namespace __detail
 
@@ -879,8 +879,8 @@  namespace std
 	operator()(const _Tp& __t, const _Up& __u) const
 	requires requires
 	{
-	  { __t < __u } -> convertible_to<bool>;
-	  { __u < __t } -> convertible_to<bool>;
+	  { __t < __u } -> __boolean_testable;
+	  { __u < __t } -> __boolean_testable;
 	}
 	{
 	  if constexpr (three_way_comparable_with<_Tp, _Up>)