Commit c8dd2446 by Jonathan Wakely

libstdc++: Implement P1878R1 "Constraining Readable Types"

	* include/bits/iterator_concepts.h (iter_difference_t, iter_value_t):
	Use remove_cvref_t.
	(readable_traits): Rename to indirectly_readable_traits.
	(readable): Rename to indirectly_readable.
	(writable): Rename to indirectly_writable.
	(__detail::__iter_exchange_move): Do not use remove_reference_t.
	(indirectly_swappable): Adjust requires expression parameter types.
	expression.
	* include/bits/ranges_algo.h (ranges::transform, ranges::replace)
	(ranges::replace_if, ranges::generate_n, ranges::generate)
	(ranges::remove): Use new name for writable.
	* include/bits/stl_iterator.h (__detail::__common_iter_has_arrow):
	Use new name for readable.
	* include/ext/pointer.h (readable_traits<_Pointer_adapter<P>>): Use
	new name for readable_traits.
	* testsuite/24_iterators/associated_types/readable.traits.cc: Likewise.
	* testsuite/24_iterators/indirect_callable/projected.cc: Adjust for
	new definition of indirectly_readable.
parent d222d8ec
2020-02-07 Jonathan Wakely <jwakely@redhat.com> 2020-02-07 Jonathan Wakely <jwakely@redhat.com>
* include/bits/iterator_concepts.h (iter_difference_t, iter_value_t):
Use remove_cvref_t.
(readable_traits): Rename to indirectly_readable_traits.
(readable): Rename to indirectly_readable.
(writable): Rename to indirectly_writable.
(__detail::__iter_exchange_move): Do not use remove_reference_t.
(indirectly_swappable): Adjust requires expression parameter types.
expression.
* include/bits/ranges_algo.h (ranges::transform, ranges::replace)
(ranges::replace_if, ranges::generate_n, ranges::generate)
(ranges::remove): Use new name for writable.
* include/bits/stl_iterator.h (__detail::__common_iter_has_arrow):
Use new name for readable.
* include/ext/pointer.h (readable_traits<_Pointer_adapter<P>>): Use
new name for readable_traits.
* testsuite/24_iterators/associated_types/readable.traits.cc: Likewise.
* testsuite/24_iterators/indirect_callable/projected.cc: Adjust for
new definition of indirectly_readable.
* include/bits/stl_iterator.h (__detail::__common_iter_ptr): Change * include/bits/stl_iterator.h (__detail::__common_iter_ptr): Change
to take parameters of common_iterator, instead of the common_iterator to take parameters of common_iterator, instead of the common_iterator
type itself. Fix argument for __common_iter_has_arrow constraint. type itself. Fix argument for __common_iter_has_arrow constraint.
......
...@@ -173,11 +173,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -173,11 +173,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// ITER_TRAITS // ITER_TRAITS
template<typename _Iter, typename _Tp = _Iter> template<typename _Iter, typename _Tp = _Iter>
using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type; using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type;
template<typename _Tp>
using __iter_diff_t = typename
__iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type;
} // namespace __detail } // namespace __detail
template<typename _Tp> template<typename _Tp>
using iter_difference_t = typename using iter_difference_t = __detail::__iter_diff_t<remove_cvref_t<_Tp>>;
__detail::__iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type;
namespace __detail namespace __detail
{ {
...@@ -188,35 +191,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -188,35 +191,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ using value_type = remove_cv_t<_Tp>; }; { using value_type = remove_cv_t<_Tp>; };
} // namespace __detail } // namespace __detail
template<typename> struct readable_traits { }; template<typename> struct indirectly_readable_traits { };
template<typename _Tp> template<typename _Tp>
struct readable_traits<_Tp*> struct indirectly_readable_traits<_Tp*>
: __detail::__cond_value_type<_Tp> : __detail::__cond_value_type<_Tp>
{ }; { };
template<typename _Iter> requires is_array_v<_Iter> template<typename _Iter> requires is_array_v<_Iter>
struct readable_traits<_Iter> struct indirectly_readable_traits<_Iter>
{ using value_type = remove_cv_t<remove_extent_t<_Iter>>; }; { using value_type = remove_cv_t<remove_extent_t<_Iter>>; };
template<typename _Iter> template<typename _Iter>
struct readable_traits<const _Iter> struct indirectly_readable_traits<const _Iter>
: readable_traits<_Iter> : indirectly_readable_traits<_Iter>
{ }; { };
template<typename _Tp> requires requires { typename _Tp::value_type; } template<typename _Tp> requires requires { typename _Tp::value_type; }
struct readable_traits<_Tp> struct indirectly_readable_traits<_Tp>
: __detail::__cond_value_type<typename _Tp::value_type> : __detail::__cond_value_type<typename _Tp::value_type>
{ }; { };
template<typename _Tp> requires requires { typename _Tp::element_type; } template<typename _Tp> requires requires { typename _Tp::element_type; }
struct readable_traits<_Tp> struct indirectly_readable_traits<_Tp>
: __detail::__cond_value_type<typename _Tp::element_type> : __detail::__cond_value_type<typename _Tp::element_type>
{ }; { };
namespace __detail
{
template<typename _Tp>
using __iter_value_t = typename
__iter_traits<_Tp, indirectly_readable_traits<_Tp>>::value_type;
} // namespace __detail
template<typename _Tp> template<typename _Tp>
using iter_value_t = typename using iter_value_t = __detail::__iter_value_t<remove_cvref_t<_Tp>>;
__detail::__iter_traits<_Tp, readable_traits<_Tp>>::value_type;
namespace __detail namespace __detail
{ {
...@@ -235,11 +244,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -235,11 +244,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& requires(_Iter __it) && requires(_Iter __it)
{ {
typename incrementable_traits<_Iter>::difference_type; typename incrementable_traits<_Iter>::difference_type;
typename readable_traits<_Iter>::value_type; typename indirectly_readable_traits<_Iter>::value_type;
typename common_reference_t<iter_reference_t<_Iter>&&, typename common_reference_t<iter_reference_t<_Iter>&&,
typename readable_traits<_Iter>::value_type&>; typename indirectly_readable_traits<_Iter>::value_type&>;
typename common_reference_t<decltype(*__it++)&&, typename common_reference_t<decltype(*__it++)&&,
typename readable_traits<_Iter>::value_type&>; typename indirectly_readable_traits<_Iter>::value_type&>;
requires signed_integral<typename incrementable_traits<_Iter>::difference_type>; requires signed_integral<typename incrementable_traits<_Iter>::difference_type>;
}; };
...@@ -248,7 +257,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -248,7 +257,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& constructible_from<_Iter> && constructible_from<_Iter>
&& is_lvalue_reference_v<iter_reference_t<_Iter>> && is_lvalue_reference_v<iter_reference_t<_Iter>>
&& same_as<remove_cvref_t<iter_reference_t<_Iter>>, && same_as<remove_cvref_t<iter_reference_t<_Iter>>,
typename readable_traits<_Iter>::value_type> typename indirectly_readable_traits<_Iter>::value_type>
&& requires(_Iter __it) && requires(_Iter __it)
{ {
{ __it++ } -> convertible_to<const _Iter&>; { __it++ } -> convertible_to<const _Iter&>;
...@@ -290,6 +299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -290,6 +299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Iter> template<typename _Iter>
concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>; concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>;
// FIXME: These have to be at namespace-scope because of PR 92103.
template<typename _Iter, bool __use_arrow = false> template<typename _Iter, bool __use_arrow = false>
struct __ptr struct __ptr
{ using type = void; }; { using type = void; };
...@@ -376,7 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -376,7 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ {
using iterator_category = typename __detail::__cat<_Iterator>::type; using iterator_category = typename __detail::__cat<_Iterator>::type;
using value_type using value_type
= typename readable_traits<_Iterator>::value_type; = typename indirectly_readable_traits<_Iterator>::value_type;
using difference_type using difference_type
= typename incrementable_traits<_Iterator>::difference_type; = typename incrementable_traits<_Iterator>::difference_type;
using pointer = typename __detail::__ptr<_Iterator, true>::type; using pointer = typename __detail::__ptr<_Iterator, true>::type;
...@@ -429,15 +439,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -429,15 +439,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// ITER_CONCEPT // ITER_CONCEPT
template<typename _Iter> template<typename _Iter>
using __iter_concept = typename __iter_concept_impl<_Iter>::type; using __iter_concept = typename __iter_concept_impl<_Iter>::type;
} // namespace __detail
/// Requirements for types that are readable by applying operator*.
template<typename _In> template<typename _In>
concept readable = requires concept __indirectly_readable_impl = requires(const _In __in)
{ {
typename iter_value_t<_In>; typename iter_value_t<_In>;
typename iter_reference_t<_In>; typename iter_reference_t<_In>;
typename iter_rvalue_reference_t<_In>; typename iter_rvalue_reference_t<_In>;
{ *__in } -> same_as<iter_reference_t<_In>>;
{ ranges::iter_move(__in) } -> same_as<iter_rvalue_reference_t<_In>>;
} }
&& common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&> && common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&>
&& common_reference_with<iter_reference_t<_In>&&, && common_reference_with<iter_reference_t<_In>&&,
...@@ -445,13 +455,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -445,13 +455,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& common_reference_with<iter_rvalue_reference_t<_In>&&, && common_reference_with<iter_rvalue_reference_t<_In>&&,
const iter_value_t<_In>&>; const iter_value_t<_In>&>;
template<readable _Tp> } // namespace __detail
/// Requirements for types that are readable by applying operator*.
template<typename _In>
concept indirectly_readable
= __detail::__indirectly_readable_impl<remove_cvref_t<_In>>;
template<indirectly_readable _Tp>
using iter_common_reference_t using iter_common_reference_t
= common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>; = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
/// Requirements for writing a value into an iterator's referenced object. /// Requirements for writing a value into an iterator's referenced object.
template<typename _Out, typename _Tp> template<typename _Out, typename _Tp>
concept writable = requires(_Out&& __o, _Tp&& __t) concept indirectly_writable = requires(_Out&& __o, _Tp&& __t)
{ {
*__o = std::forward<_Tp>(__t); *__o = std::forward<_Tp>(__t);
*std::forward<_Out>(__o) = std::forward<_Tp>(__t); *std::forward<_Out>(__o) = std::forward<_Tp>(__t);
...@@ -523,13 +540,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -523,13 +540,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Iter> template<typename _Iter>
concept input_iterator = input_or_output_iterator<_Iter> concept input_iterator = input_or_output_iterator<_Iter>
&& readable<_Iter> && indirectly_readable<_Iter>
&& requires { typename __detail::__iter_concept<_Iter>; } && requires { typename __detail::__iter_concept<_Iter>; }
&& derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>; && derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>;
template<typename _Iter, typename _Tp> template<typename _Iter, typename _Tp>
concept output_iterator = input_or_output_iterator<_Iter> concept output_iterator = input_or_output_iterator<_Iter>
&& writable<_Iter, _Tp> && indirectly_writable<_Iter, _Tp>
&& requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); }; && requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); };
template<typename _Iter> template<typename _Iter>
...@@ -579,7 +596,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -579,7 +596,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// [indirectcallable.indirectinvocable], indirect callables // [indirectcallable.indirectinvocable], indirect callables
template<typename _Fn, typename _Iter> template<typename _Fn, typename _Iter>
concept indirectly_unary_invocable = readable<_Iter> concept indirectly_unary_invocable = indirectly_readable<_Iter>
&& copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&> && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&>
&& invocable<_Fn&, iter_reference_t<_Iter>> && invocable<_Fn&, iter_reference_t<_Iter>>
&& invocable<_Fn&, iter_common_reference_t<_Iter>> && invocable<_Fn&, iter_common_reference_t<_Iter>>
...@@ -587,7 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -587,7 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
template<typename _Fn, typename _Iter> template<typename _Fn, typename _Iter>
concept indirectly_regular_unary_invocable = readable<_Iter> concept indirectly_regular_unary_invocable = indirectly_readable<_Iter>
&& copy_constructible<_Fn> && copy_constructible<_Fn>
&& regular_invocable<_Fn&, iter_value_t<_Iter>&> && regular_invocable<_Fn&, iter_value_t<_Iter>&>
&& regular_invocable<_Fn&, iter_reference_t<_Iter>> && regular_invocable<_Fn&, iter_reference_t<_Iter>>
...@@ -596,13 +613,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -596,13 +613,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
template<typename _Fn, typename _Iter> template<typename _Fn, typename _Iter>
concept indirect_unary_predicate = readable<_Iter> concept indirect_unary_predicate = indirectly_readable<_Iter>
&& copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&> && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&>
&& predicate<_Fn&, iter_reference_t<_Iter>> && predicate<_Fn&, iter_reference_t<_Iter>>
&& predicate<_Fn&, iter_common_reference_t<_Iter>>; && predicate<_Fn&, iter_common_reference_t<_Iter>>;
template<typename _Fn, typename _I1, typename _I2> template<typename _Fn, typename _I1, typename _I2>
concept indirect_binary_predicate = readable<_I1> && readable<_I2> concept indirect_binary_predicate
= indirectly_readable<_I1> && indirectly_readable<_I2>
&& copy_constructible<_Fn> && copy_constructible<_Fn>
&& predicate<_Fn&, iter_value_t<_I1>&, iter_value_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_value_t<_I1>&, iter_reference_t<_I2>>
...@@ -612,7 +630,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -612,7 +630,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
iter_common_reference_t<_I2>>; iter_common_reference_t<_I2>>;
template<typename _Fn, typename _I1, typename _I2 = _I1> template<typename _Fn, typename _I1, typename _I2 = _I1>
concept indirect_equivalence_relation = readable<_I1> && readable<_I2> concept indirect_equivalence_relation
= indirectly_readable<_I1> && indirectly_readable<_I2>
&& copy_constructible<_Fn> && copy_constructible<_Fn>
&& equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_value_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_value_t<_I1>&, iter_reference_t<_I2>>
...@@ -623,7 +642,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -623,7 +642,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
iter_common_reference_t<_I2>>; iter_common_reference_t<_I2>>;
template<typename _Fn, typename _I1, typename _I2 = _I1> template<typename _Fn, typename _I1, typename _I2 = _I1>
concept indirect_strict_weak_order = readable<_I1> && readable<_I2> concept indirect_strict_weak_order
= indirectly_readable<_I1> && indirectly_readable<_I2>
&& copy_constructible<_Fn> && copy_constructible<_Fn>
&& strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
&& strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
...@@ -633,12 +653,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -633,12 +653,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
iter_common_reference_t<_I2>>; iter_common_reference_t<_I2>>;
template<typename _Fn, typename... _Is> template<typename _Fn, typename... _Is>
requires (readable<_Is> && ...) requires (indirectly_readable<_Is> && ...)
&& invocable<_Fn, iter_reference_t<_Is>...> && invocable<_Fn, iter_reference_t<_Is>...>
using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>; using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>;
/// [projected], projected /// [projected], projected
template<readable _Iter, indirectly_regular_unary_invocable<_Iter> _Proj> template<indirectly_readable _Iter,
indirectly_regular_unary_invocable<_Iter> _Proj>
struct projected struct projected
{ {
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>; using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
...@@ -655,23 +676,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -655,23 +676,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// [alg.req.ind.move], concept `indirectly_movable` /// [alg.req.ind.move], concept `indirectly_movable`
template<typename _In, typename _Out> template<typename _In, typename _Out>
concept indirectly_movable = readable<_In> concept indirectly_movable = indirectly_readable<_In>
&& writable<_Out, iter_rvalue_reference_t<_In>>; && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>;
template<typename _In, typename _Out> template<typename _In, typename _Out>
concept indirectly_movable_storable = indirectly_movable<_In, _Out> concept indirectly_movable_storable = indirectly_movable<_In, _Out>
&& writable<_Out, iter_value_t<_In>> && movable<iter_value_t<_In>> && indirectly_writable<_Out, iter_value_t<_In>>
&& movable<iter_value_t<_In>>
&& constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>> && constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>>
&& assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>; && assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>;
/// [alg.req.ind.copy], concept `indirectly_copyable` /// [alg.req.ind.copy], concept `indirectly_copyable`
template<typename _In, typename _Out> template<typename _In, typename _Out>
concept indirectly_copyable = readable<_In> concept indirectly_copyable = indirectly_readable<_In>
&& writable<_Out, iter_reference_t<_In>>; && indirectly_writable<_Out, iter_reference_t<_In>>;
template<typename _In, typename _Out> template<typename _In, typename _Out>
concept indirectly_copyable_storable = indirectly_copyable<_In, _Out> concept indirectly_copyable_storable = indirectly_copyable<_In, _Out>
&& writable<_Out, const iter_value_t<_In>&> && indirectly_writable<_Out, const iter_value_t<_In>&>
&& copyable<iter_value_t<_In>> && copyable<iter_value_t<_In>>
&& constructible_from<iter_value_t<_In>, iter_reference_t<_In>> && constructible_from<iter_value_t<_In>, iter_reference_t<_In>>
&& assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>; && assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>;
...@@ -692,12 +714,12 @@ namespace ranges ...@@ -692,12 +714,12 @@ namespace ranges
}; };
template<typename _Xp, typename _Yp> template<typename _Xp, typename _Yp>
constexpr iter_value_t<remove_reference_t<_Xp>> constexpr iter_value_t<_Xp>
__iter_exchange_move(_Xp&& __x, _Yp&& __y) __iter_exchange_move(_Xp&& __x, _Yp&& __y)
noexcept(noexcept(iter_value_t<remove_reference_t<_Xp>>(iter_move(__x))) noexcept(noexcept(iter_value_t<_Xp>(iter_move(__x)))
&& noexcept(*__x = iter_move(__y))) && noexcept(*__x = iter_move(__y)))
{ {
iter_value_t<remove_reference_t<_Xp>> __old_value(iter_move(__x)); iter_value_t<_Xp> __old_value(iter_move(__x));
*__x = iter_move(__y); *__x = iter_move(__y);
return __old_value; return __old_value;
} }
...@@ -712,8 +734,9 @@ namespace ranges ...@@ -712,8 +734,9 @@ namespace ranges
if constexpr (__adl_iswap<_Tp, _Up>) if constexpr (__adl_iswap<_Tp, _Up>)
return noexcept(iter_swap(std::declval<_Tp>(), return noexcept(iter_swap(std::declval<_Tp>(),
std::declval<_Up>())); std::declval<_Up>()));
else if constexpr (readable<_Tp> && readable<_Up> else if constexpr (indirectly_readable<_Tp>
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>) && indirectly_readable<_Up>
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
return noexcept(ranges::swap(*std::declval<_Tp>(), return noexcept(ranges::swap(*std::declval<_Tp>(),
*std::declval<_Up>())); *std::declval<_Up>()));
else else
...@@ -725,8 +748,8 @@ namespace ranges ...@@ -725,8 +748,8 @@ namespace ranges
public: public:
template<typename _Tp, typename _Up> template<typename _Tp, typename _Up>
requires __adl_iswap<_Tp, _Up> requires __adl_iswap<_Tp, _Up>
|| (readable<remove_reference_t<_Tp>> || (indirectly_readable<remove_reference_t<_Tp>>
&& readable<remove_reference_t<_Up>> && indirectly_readable<remove_reference_t<_Up>>
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>) && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
|| (indirectly_movable_storable<_Tp, _Up> || (indirectly_movable_storable<_Tp, _Up>
&& indirectly_movable_storable<_Up, _Tp>) && indirectly_movable_storable<_Up, _Tp>)
...@@ -736,8 +759,9 @@ namespace ranges ...@@ -736,8 +759,9 @@ namespace ranges
{ {
if constexpr (__adl_iswap<_Tp, _Up>) if constexpr (__adl_iswap<_Tp, _Up>)
iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2)); iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2));
else if constexpr (readable<_Tp> && readable<_Up> else if constexpr (indirectly_readable<_Tp>
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>) && indirectly_readable<_Up>
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
ranges::swap(*__e1, *__e2); ranges::swap(*__e1, *__e2);
else else
*__e1 = __iter_exchange_move(__e2, __e1); *__e1 = __iter_exchange_move(__e2, __e1);
...@@ -754,8 +778,9 @@ namespace ranges ...@@ -754,8 +778,9 @@ namespace ranges
/// [alg.req.ind.swap], concept `indirectly_swappable` /// [alg.req.ind.swap], concept `indirectly_swappable`
template<typename _I1, typename _I2 = _I1> template<typename _I1, typename _I2 = _I1>
concept indirectly_swappable = readable<_I1> && readable<_I2> concept indirectly_swappable
&& requires(_I1& __i1, _I2& __i2) = indirectly_readable<_I1> && indirectly_readable<_I2>
&& requires(const _I1 __i1, const _I2 __i2)
{ {
ranges::iter_swap(__i1, __i1); ranges::iter_swap(__i1, __i1);
ranges::iter_swap(__i2, __i2); ranges::iter_swap(__i2, __i2);
......
...@@ -1219,7 +1219,9 @@ namespace ranges ...@@ -1219,7 +1219,9 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent, template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
weakly_incrementable _Out, weakly_incrementable _Out,
copy_constructible _Fp, typename _Proj = identity> copy_constructible _Fp, typename _Proj = identity>
requires writable<_Out, indirect_result_t<_Fp&, projected<_Iter, _Proj>>> requires indirectly_writable<_Out,
indirect_result_t<_Fp&,
projected<_Iter, _Proj>>>
constexpr unary_transform_result<_Iter, _Out> constexpr unary_transform_result<_Iter, _Out>
transform(_Iter __first1, _Sent __last1, _Out __result, transform(_Iter __first1, _Sent __last1, _Out __result,
_Fp __op, _Proj __proj = {}) _Fp __op, _Proj __proj = {})
...@@ -1231,9 +1233,9 @@ namespace ranges ...@@ -1231,9 +1233,9 @@ namespace ranges
template<input_range _Range, weakly_incrementable _Out, template<input_range _Range, weakly_incrementable _Out,
copy_constructible _Fp, typename _Proj = identity> copy_constructible _Fp, typename _Proj = identity>
requires writable<_Out, requires indirectly_writable<_Out,
indirect_result_t<_Fp&, projected<iterator_t<_Range>, indirect_result_t<_Fp&,
_Proj>>> projected<iterator_t<_Range>, _Proj>>>
constexpr unary_transform_result<safe_iterator_t<_Range>, _Out> constexpr unary_transform_result<safe_iterator_t<_Range>, _Out>
transform(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) transform(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {})
{ {
...@@ -1268,8 +1270,10 @@ namespace ranges ...@@ -1268,8 +1270,10 @@ namespace ranges
input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
weakly_incrementable _Out, copy_constructible _Fp, weakly_incrementable _Out, copy_constructible _Fp,
typename _Proj1 = identity, typename _Proj2 = identity> typename _Proj1 = identity, typename _Proj2 = identity>
requires writable<_Out, indirect_result_t<_Fp&, projected<_Iter1, _Proj1>, requires indirectly_writable<_Out,
projected<_Iter2, _Proj2>>> indirect_result_t<_Fp&,
projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>>>
constexpr binary_transform_result<_Iter1, _Iter2, _Out> constexpr binary_transform_result<_Iter1, _Iter2, _Out>
transform(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, transform(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
_Out __result, _Fp __binary_op, _Out __result, _Fp __binary_op,
...@@ -1286,11 +1290,10 @@ namespace ranges ...@@ -1286,11 +1290,10 @@ namespace ranges
template<input_range _Range1, input_range _Range2, template<input_range _Range1, input_range _Range2,
weakly_incrementable _Out, copy_constructible _Fp, weakly_incrementable _Out, copy_constructible _Fp,
typename _Proj1 = identity, typename _Proj2 = identity> typename _Proj1 = identity, typename _Proj2 = identity>
requires writable<_Out, indirect_result_t<_Fp&, requires indirectly_writable<_Out,
projected<iterator_t<_Range1>, indirect_result_t<_Fp&,
_Proj1>, projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, projected<iterator_t<_Range2>, _Proj2>>>
_Proj2>>>
constexpr binary_transform_result<safe_iterator_t<_Range1>, constexpr binary_transform_result<safe_iterator_t<_Range1>,
safe_iterator_t<_Range2>, _Out> safe_iterator_t<_Range2>, _Out>
transform(_Range1&& __r1, _Range2&& __r2, _Out __result, transform(_Range1&& __r1, _Range2&& __r2, _Out __result,
...@@ -1304,9 +1307,9 @@ namespace ranges ...@@ -1304,9 +1307,9 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent, template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp1, typename _Tp2, typename _Proj = identity> typename _Tp1, typename _Tp2, typename _Proj = identity>
requires writable<_Iter, const _Tp2&> && requires indirectly_writable<_Iter, const _Tp2&>
indirect_binary_predicate<ranges::equal_to, && indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>,
projected<_Iter, _Proj>, const _Tp1*> const _Tp1*>
constexpr _Iter constexpr _Iter
replace(_Iter __first, _Sent __last, replace(_Iter __first, _Sent __last,
const _Tp1& __old_value, const _Tp2& __new_value, const _Tp1& __old_value, const _Tp2& __new_value,
...@@ -1320,10 +1323,10 @@ namespace ranges ...@@ -1320,10 +1323,10 @@ namespace ranges
template<input_range _Range, template<input_range _Range,
typename _Tp1, typename _Tp2, typename _Proj = identity> typename _Tp1, typename _Tp2, typename _Proj = identity>
requires writable<iterator_t<_Range>, const _Tp2&> && requires indirectly_writable<iterator_t<_Range>, const _Tp2&>
indirect_binary_predicate<ranges::equal_to, && indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>, projected<iterator_t<_Range>, _Proj>,
const _Tp1*> const _Tp1*>
constexpr safe_iterator_t<_Range> constexpr safe_iterator_t<_Range>
replace(_Range&& __r, replace(_Range&& __r,
const _Tp1& __old_value, const _Tp2& __new_value, const _Tp1& __old_value, const _Tp2& __new_value,
...@@ -1336,7 +1339,7 @@ namespace ranges ...@@ -1336,7 +1339,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent, template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp, typename _Proj = identity, typename _Tp, typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
requires writable<_Iter, const _Tp&> requires indirectly_writable<_Iter, const _Tp&>
constexpr _Iter constexpr _Iter
replace_if(_Iter __first, _Sent __last, replace_if(_Iter __first, _Sent __last,
_Pred __pred, const _Tp& __new_value, _Proj __proj = {}) _Pred __pred, const _Tp& __new_value, _Proj __proj = {})
...@@ -1349,7 +1352,7 @@ namespace ranges ...@@ -1349,7 +1352,7 @@ namespace ranges
template<input_range _Range, typename _Tp, typename _Proj = identity, template<input_range _Range, typename _Tp, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
requires writable<iterator_t<_Range>, const _Tp&> requires indirectly_writable<iterator_t<_Range>, const _Tp&>
constexpr safe_iterator_t<_Range> constexpr safe_iterator_t<_Range>
replace_if(_Range&& __r, replace_if(_Range&& __r,
_Pred __pred, const _Tp& __new_value, _Proj __proj = {}) _Pred __pred, const _Tp& __new_value, _Proj __proj = {})
...@@ -1496,7 +1499,8 @@ namespace ranges ...@@ -1496,7 +1499,8 @@ namespace ranges
} }
template<input_or_output_iterator _Out, copy_constructible _Fp> template<input_or_output_iterator _Out, copy_constructible _Fp>
requires invocable<_Fp&> && writable<_Out, invoke_result_t<_Fp&>> requires invocable<_Fp&>
&& indirectly_writable<_Out, invoke_result_t<_Fp&>>
constexpr _Out constexpr _Out
generate_n(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) generate_n(_Out __first, iter_difference_t<_Out> __n, _Fp __gen)
{ {
...@@ -1507,7 +1511,8 @@ namespace ranges ...@@ -1507,7 +1511,8 @@ namespace ranges
template<input_or_output_iterator _Out, sentinel_for<_Out> _Sent, template<input_or_output_iterator _Out, sentinel_for<_Out> _Sent,
copy_constructible _Fp> copy_constructible _Fp>
requires invocable<_Fp&> && writable<_Out, invoke_result_t<_Fp&>> requires invocable<_Fp&>
&& indirectly_writable<_Out, invoke_result_t<_Fp&>>
constexpr _Out constexpr _Out
generate(_Out __first, _Sent __last, _Fp __gen) generate(_Out __first, _Sent __last, _Fp __gen)
{ {
...@@ -1573,10 +1578,10 @@ namespace ranges ...@@ -1573,10 +1578,10 @@ namespace ranges
} }
template<forward_range _Range, typename _Tp, typename _Proj = identity> template<forward_range _Range, typename _Tp, typename _Proj = identity>
requires permutable<iterator_t<_Range>> && requires permutable<iterator_t<_Range>>
indirect_binary_predicate<ranges::equal_to, && indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>, projected<iterator_t<_Range>, _Proj>,
const _Tp*> const _Tp*>
constexpr safe_subrange_t<_Range> constexpr safe_subrange_t<_Range>
remove(_Range&& __r, const _Tp& __value, _Proj __proj = {}) remove(_Range&& __r, const _Tp& __value, _Proj __proj = {})
{ {
......
...@@ -1417,7 +1417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1417,7 +1417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}; };
template<typename _It> template<typename _It>
concept __common_iter_has_arrow = readable<const _It> concept __common_iter_has_arrow = indirectly_readable<const _It>
&& (requires(const _It& __it) { __it.operator->(); } && (requires(const _It& __it) { __it.operator->(); }
|| is_reference_v<iter_reference_t<_It>> || is_reference_v<iter_reference_t<_It>>
|| constructible_from<iter_value_t<_It>, iter_reference_t<_It>>); || constructible_from<iter_value_t<_It>, iter_reference_t<_It>>);
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
# include <bits/ptr_traits.h> # include <bits/ptr_traits.h>
#endif #endif
#if __cplusplus > 201703L #if __cplusplus > 201703L
# include <iterator> // for readable_traits # include <iterator> // for indirectly_readable_traits
#endif #endif
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
...@@ -598,11 +598,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -598,11 +598,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}; };
#if __cpp_lib_concepts #if __cpp_lib_concepts
template<typename _Storage_policy> template<typename _Policy>
struct readable_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>> struct indirectly_readable_traits<__gnu_cxx::_Pointer_adapter<_Policy>>
{ {
using value_type using value_type
= typename __gnu_cxx::_Pointer_adapter<_Storage_policy>::value_type; = typename __gnu_cxx::_Pointer_adapter<_Policy>::value_type;
}; };
#endif #endif
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
......
...@@ -24,9 +24,9 @@ struct none; ...@@ -24,9 +24,9 @@ struct none;
template<typename T> template<typename T>
concept has_readable_traits_type concept has_readable_traits_type
= requires { typename std::readable_traits<T>::value_type; }; = requires { typename std::indirectly_readable_traits<T>::value_type; };
// Check std::readable_traits<T>::value_type is U (or doesn't exist). // Check std::indirectly_readable_traits<T>::value_type is U (or doesn't exist).
template<typename T, typename U> template<typename T, typename U>
concept check_readable_traits concept check_readable_traits
= (has_readable_traits_type<T> != std::same_as<U, none>); = (has_readable_traits_type<T> != std::same_as<U, none>);
...@@ -62,7 +62,7 @@ static_assert( check_readable_traits<const D, none> ); ...@@ -62,7 +62,7 @@ static_assert( check_readable_traits<const D, none> );
struct E { }; struct E { };
template<> template<>
struct std::readable_traits<E> { using value_type = long; }; struct std::indirectly_readable_traits<E> { using value_type = long; };
static_assert( check_readable_traits<E, long> ); static_assert( check_readable_traits<E, long> );
static_assert( check_readable_traits<const E, long> ); static_assert( check_readable_traits<const E, long> );
...@@ -103,7 +103,7 @@ static_assert( check_alias<F, std::iterator_traits<F>::value_type> ); ...@@ -103,7 +103,7 @@ static_assert( check_alias<F, std::iterator_traits<F>::value_type> );
struct G { }; struct G { };
template<> template<>
struct std::readable_traits<G> { using value_type = G; }; struct std::indirectly_readable_traits<G> { using value_type = G; };
template<> template<>
struct std::iterator_traits<G> { using value_type = int; }; struct std::iterator_traits<G> { using value_type = int; };
// iterator_traits<G> is specialized, so use its value_type. // iterator_traits<G> is specialized, so use its value_type.
...@@ -111,7 +111,7 @@ static_assert( check_alias<G, std::iterator_traits<G>::value_type> ); ...@@ -111,7 +111,7 @@ static_assert( check_alias<G, std::iterator_traits<G>::value_type> );
struct H { }; struct H { };
template<> template<>
struct std::readable_traits<H> { using value_type = H; }; struct std::indirectly_readable_traits<H> { using value_type = H; };
template<> template<>
struct std::iterator_traits<H> struct std::iterator_traits<H>
{ {
...@@ -128,8 +128,8 @@ struct I ...@@ -128,8 +128,8 @@ struct I
using value_type = I; using value_type = I;
}; };
// iterator_traits<I> is not specialized, and no standard specialization // iterator_traits<I> is not specialized, and no standard specialization
// matches, so use readable_traits. // matches, so use indirectly_readable_traits.
static_assert( check_alias<I, std::readable_traits<I>::value_type> ); static_assert( check_alias<I, std::indirectly_readable_traits<I>::value_type> );
struct J struct J
{ {
......
...@@ -29,9 +29,11 @@ static_assert(std::same_as<decltype(*std::declval<const PI<int*>&>()), int&>); ...@@ -29,9 +29,11 @@ static_assert(std::same_as<decltype(*std::declval<const PI<int*>&>()), int&>);
struct X struct X
{ {
using value_type = char*; using value_type = char*;
char* const& operator*() &; char* const& operator*() const;
}; };
static_assert( std::readable<X> ); static_assert( std::indirectly_readable<X> );
static_assert( std::indirectly_readable<X&> );
static_assert( std::indirectly_readable<const X> );
static_assert(std::same_as<PI<X>::value_type, char*>); static_assert(std::same_as<PI<X>::value_type, char*>);
static_assert(std::same_as<decltype(*std::declval<PI<X>&>()), char* const&>); static_assert(std::same_as<decltype(*std::declval<PI<X>&>()), char* const&>);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment