2020-02-17 Jonathan Wakely <jwakely@redhat.com>
+ P1964R2 Wording for boolean-testable
+ * 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.
+
P1970R2 Consistency for size() functions: Add ranges::ssize
* include/bits/range_access.h (_SSize, ssize): Define for C++20.
* testsuite/std/ranges/access/ssize.cc: New test.
const _Tp& __value, _Proj __proj = {}) const
{
while (__first != __last
- && !(std::__invoke(__proj, *__first) == __value))
+ && !(bool)(std::__invoke(__proj, *__first) == __value))
++__first;
return __first;
}
{
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;
}
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;
// [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
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
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>
__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>
/// [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>
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
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>)