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>
* 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
to take parameters of common_iterator, instead of the common_iterator
type itself. Fix argument for __common_iter_has_arrow constraint.
......
......@@ -1219,7 +1219,9 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
weakly_incrementable _Out,
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>
transform(_Iter __first1, _Sent __last1, _Out __result,
_Fp __op, _Proj __proj = {})
......@@ -1231,9 +1233,9 @@ namespace ranges
template<input_range _Range, weakly_incrementable _Out,
copy_constructible _Fp, typename _Proj = identity>
requires writable<_Out,
indirect_result_t<_Fp&, projected<iterator_t<_Range>,
_Proj>>>
requires indirectly_writable<_Out,
indirect_result_t<_Fp&,
projected<iterator_t<_Range>, _Proj>>>
constexpr unary_transform_result<safe_iterator_t<_Range>, _Out>
transform(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {})
{
......@@ -1268,7 +1270,9 @@ namespace ranges
input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
weakly_incrementable _Out, copy_constructible _Fp,
typename _Proj1 = identity, typename _Proj2 = identity>
requires writable<_Out, indirect_result_t<_Fp&, projected<_Iter1, _Proj1>,
requires indirectly_writable<_Out,
indirect_result_t<_Fp&,
projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>>>
constexpr binary_transform_result<_Iter1, _Iter2, _Out>
transform(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
......@@ -1286,11 +1290,10 @@ namespace ranges
template<input_range _Range1, input_range _Range2,
weakly_incrementable _Out, copy_constructible _Fp,
typename _Proj1 = identity, typename _Proj2 = identity>
requires writable<_Out, indirect_result_t<_Fp&,
projected<iterator_t<_Range1>,
_Proj1>,
projected<iterator_t<_Range2>,
_Proj2>>>
requires indirectly_writable<_Out,
indirect_result_t<_Fp&,
projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, _Proj2>>>
constexpr binary_transform_result<safe_iterator_t<_Range1>,
safe_iterator_t<_Range2>, _Out>
transform(_Range1&& __r1, _Range2&& __r2, _Out __result,
......@@ -1304,9 +1307,9 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp1, typename _Tp2, typename _Proj = identity>
requires writable<_Iter, const _Tp2&> &&
indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>, const _Tp1*>
requires indirectly_writable<_Iter, const _Tp2&>
&& indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>,
const _Tp1*>
constexpr _Iter
replace(_Iter __first, _Sent __last,
const _Tp1& __old_value, const _Tp2& __new_value,
......@@ -1320,8 +1323,8 @@ namespace ranges
template<input_range _Range,
typename _Tp1, typename _Tp2, typename _Proj = identity>
requires writable<iterator_t<_Range>, const _Tp2&> &&
indirect_binary_predicate<ranges::equal_to,
requires indirectly_writable<iterator_t<_Range>, const _Tp2&>
&& indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp1*>
constexpr safe_iterator_t<_Range>
......@@ -1336,7 +1339,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp, typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
requires writable<_Iter, const _Tp&>
requires indirectly_writable<_Iter, const _Tp&>
constexpr _Iter
replace_if(_Iter __first, _Sent __last,
_Pred __pred, const _Tp& __new_value, _Proj __proj = {})
......@@ -1349,7 +1352,7 @@ namespace ranges
template<input_range _Range, typename _Tp, typename _Proj = identity,
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>
replace_if(_Range&& __r,
_Pred __pred, const _Tp& __new_value, _Proj __proj = {})
......@@ -1496,7 +1499,8 @@ namespace ranges
}
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
generate_n(_Out __first, iter_difference_t<_Out> __n, _Fp __gen)
{
......@@ -1507,7 +1511,8 @@ namespace ranges
template<input_or_output_iterator _Out, sentinel_for<_Out> _Sent,
copy_constructible _Fp>
requires invocable<_Fp&> && writable<_Out, invoke_result_t<_Fp&>>
requires invocable<_Fp&>
&& indirectly_writable<_Out, invoke_result_t<_Fp&>>
constexpr _Out
generate(_Out __first, _Sent __last, _Fp __gen)
{
......@@ -1573,8 +1578,8 @@ namespace ranges
}
template<forward_range _Range, typename _Tp, typename _Proj = identity>
requires permutable<iterator_t<_Range>> &&
indirect_binary_predicate<ranges::equal_to,
requires permutable<iterator_t<_Range>>
&& indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
constexpr safe_subrange_t<_Range>
......
......@@ -1417,7 +1417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
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->(); }
|| is_reference_v<iter_reference_t<_It>>
|| constructible_from<iter_value_t<_It>, iter_reference_t<_It>>);
......
......@@ -47,7 +47,7 @@
# include <bits/ptr_traits.h>
#endif
#if __cplusplus > 201703L
# include <iterator> // for readable_traits
# include <iterator> // for indirectly_readable_traits
#endif
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
......@@ -598,11 +598,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
#if __cpp_lib_concepts
template<typename _Storage_policy>
struct readable_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>>
template<typename _Policy>
struct indirectly_readable_traits<__gnu_cxx::_Pointer_adapter<_Policy>>
{
using value_type
= typename __gnu_cxx::_Pointer_adapter<_Storage_policy>::value_type;
= typename __gnu_cxx::_Pointer_adapter<_Policy>::value_type;
};
#endif
_GLIBCXX_END_NAMESPACE_VERSION
......
......@@ -24,9 +24,9 @@ struct none;
template<typename T>
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>
concept check_readable_traits
= (has_readable_traits_type<T> != std::same_as<U, none>);
......@@ -62,7 +62,7 @@ static_assert( check_readable_traits<const D, none> );
struct E { };
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<const E, long> );
......@@ -103,7 +103,7 @@ static_assert( check_alias<F, std::iterator_traits<F>::value_type> );
struct G { };
template<>
struct std::readable_traits<G> { using value_type = G; };
struct std::indirectly_readable_traits<G> { using value_type = G; };
template<>
struct std::iterator_traits<G> { using value_type = int; };
// 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> );
struct H { };
template<>
struct std::readable_traits<H> { using value_type = H; };
struct std::indirectly_readable_traits<H> { using value_type = H; };
template<>
struct std::iterator_traits<H>
{
......@@ -128,8 +128,8 @@ struct I
using value_type = I;
};
// iterator_traits<I> is not specialized, and no standard specialization
// matches, so use readable_traits.
static_assert( check_alias<I, std::readable_traits<I>::value_type> );
// matches, so use indirectly_readable_traits.
static_assert( check_alias<I, std::indirectly_readable_traits<I>::value_type> );
struct J
{
......
......@@ -29,9 +29,11 @@ static_assert(std::same_as<decltype(*std::declval<const PI<int*>&>()), int&>);
struct X
{
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<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