From c8dd2446f597e6d1581414a9c02ff329285181a9 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 6 Feb 2020 11:21:25 +0000 Subject: [PATCH] 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

>): 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. --- libstdc++-v3/ChangeLog | 19 +++ libstdc++-v3/include/bits/iterator_concepts.h | 121 +++++++++++------- libstdc++-v3/include/bits/ranges_algo.h | 57 +++++---- libstdc++-v3/include/bits/stl_iterator.h | 2 +- libstdc++-v3/include/ext/pointer.h | 8 +- .../associated_types/readable.traits.cc | 14 +- .../indirect_callable/projected.cc | 6 +- 7 files changed, 139 insertions(+), 88 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4d8ea9d8212..1781e63f1cc 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,24 @@ 2020-02-07 Jonathan Wakely + * 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

>): 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. diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index d9b8958d0a7..04c862a4b97 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -173,11 +173,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // ITER_TRAITS template using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type; + + template + using __iter_diff_t = typename + __iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type; } // namespace __detail template - using iter_difference_t = typename - __detail::__iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type; + using iter_difference_t = __detail::__iter_diff_t>; namespace __detail { @@ -188,35 +191,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { using value_type = remove_cv_t<_Tp>; }; } // namespace __detail - template struct readable_traits { }; + template struct indirectly_readable_traits { }; template - struct readable_traits<_Tp*> + struct indirectly_readable_traits<_Tp*> : __detail::__cond_value_type<_Tp> { }; template requires is_array_v<_Iter> - struct readable_traits<_Iter> + struct indirectly_readable_traits<_Iter> { using value_type = remove_cv_t>; }; template - struct readable_traits - : readable_traits<_Iter> + struct indirectly_readable_traits + : indirectly_readable_traits<_Iter> { }; template requires requires { typename _Tp::value_type; } - struct readable_traits<_Tp> + struct indirectly_readable_traits<_Tp> : __detail::__cond_value_type { }; template requires requires { typename _Tp::element_type; } - struct readable_traits<_Tp> + struct indirectly_readable_traits<_Tp> : __detail::__cond_value_type { }; + namespace __detail + { + template + using __iter_value_t = typename + __iter_traits<_Tp, indirectly_readable_traits<_Tp>>::value_type; + } // namespace __detail + template - using iter_value_t = typename - __detail::__iter_traits<_Tp, readable_traits<_Tp>>::value_type; + using iter_value_t = __detail::__iter_value_t>; namespace __detail { @@ -235,11 +244,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && requires(_Iter __it) { typename incrementable_traits<_Iter>::difference_type; - typename readable_traits<_Iter>::value_type; + typename indirectly_readable_traits<_Iter>::value_type; typename common_reference_t&&, - typename readable_traits<_Iter>::value_type&>; + typename indirectly_readable_traits<_Iter>::value_type&>; typename common_reference_t::value_type&>; + typename indirectly_readable_traits<_Iter>::value_type&>; requires signed_integral::difference_type>; }; @@ -248,7 +257,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && constructible_from<_Iter> && is_lvalue_reference_v> && same_as>, - typename readable_traits<_Iter>::value_type> + typename indirectly_readable_traits<_Iter>::value_type> && requires(_Iter __it) { { __it++ } -> convertible_to; @@ -290,6 +299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>; + // FIXME: These have to be at namespace-scope because of PR 92103. template struct __ptr { using type = void; }; @@ -376,7 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { using iterator_category = typename __detail::__cat<_Iterator>::type; using value_type - = typename readable_traits<_Iterator>::value_type; + = typename indirectly_readable_traits<_Iterator>::value_type; using difference_type = typename incrementable_traits<_Iterator>::difference_type; using pointer = typename __detail::__ptr<_Iterator, true>::type; @@ -429,15 +439,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // ITER_CONCEPT template using __iter_concept = typename __iter_concept_impl<_Iter>::type; - } // namespace __detail - /// Requirements for types that are readable by applying operator*. template - concept readable = requires + concept __indirectly_readable_impl = requires(const _In __in) { typename iter_value_t<_In>; typename iter_reference_t<_In>; typename iter_rvalue_reference_t<_In>; + { *__in } -> same_as>; + { ranges::iter_move(__in) } -> same_as>; } && common_reference_with&&, iter_value_t<_In>&> && common_reference_with&&, @@ -445,13 +455,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && common_reference_with&&, const iter_value_t<_In>&>; - template + } // namespace __detail + + /// Requirements for types that are readable by applying operator*. + template + concept indirectly_readable + = __detail::__indirectly_readable_impl>; + + template using iter_common_reference_t = common_reference_t, iter_value_t<_Tp>&>; /// Requirements for writing a value into an iterator's referenced object. template - concept writable = requires(_Out&& __o, _Tp&& __t) + concept indirectly_writable = requires(_Out&& __o, _Tp&& __t) { *__o = std::forward<_Tp>(__t); *std::forward<_Out>(__o) = std::forward<_Tp>(__t); @@ -523,13 +540,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template concept input_iterator = input_or_output_iterator<_Iter> - && readable<_Iter> + && indirectly_readable<_Iter> && requires { typename __detail::__iter_concept<_Iter>; } && derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>; template 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); }; template @@ -579,7 +596,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [indirectcallable.indirectinvocable], indirect callables template - concept indirectly_unary_invocable = readable<_Iter> + concept indirectly_unary_invocable = indirectly_readable<_Iter> && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&> && invocable<_Fn&, iter_reference_t<_Iter>> && invocable<_Fn&, iter_common_reference_t<_Iter>> @@ -587,7 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; template - concept indirectly_regular_unary_invocable = readable<_Iter> + concept indirectly_regular_unary_invocable = indirectly_readable<_Iter> && copy_constructible<_Fn> && regular_invocable<_Fn&, iter_value_t<_Iter>&> && regular_invocable<_Fn&, iter_reference_t<_Iter>> @@ -596,13 +613,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; template - concept indirect_unary_predicate = readable<_Iter> + concept indirect_unary_predicate = indirectly_readable<_Iter> && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&> && predicate<_Fn&, iter_reference_t<_Iter>> && predicate<_Fn&, iter_common_reference_t<_Iter>>; template - concept indirect_binary_predicate = readable<_I1> && readable<_I2> + concept indirect_binary_predicate + = indirectly_readable<_I1> && indirectly_readable<_I2> && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> @@ -612,7 +630,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iter_common_reference_t<_I2>>; template - concept indirect_equivalence_relation = readable<_I1> && readable<_I2> + concept indirect_equivalence_relation + = indirectly_readable<_I1> && indirectly_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>> @@ -623,7 +642,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iter_common_reference_t<_I2>>; template - concept indirect_strict_weak_order = readable<_I1> && readable<_I2> + concept indirect_strict_weak_order + = indirectly_readable<_I1> && indirectly_readable<_I2> && copy_constructible<_Fn> && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> @@ -633,12 +653,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iter_common_reference_t<_I2>>; template - requires (readable<_Is> && ...) + requires (indirectly_readable<_Is> && ...) && invocable<_Fn, iter_reference_t<_Is>...> using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>; /// [projected], projected - template _Proj> + template _Proj> struct projected { using value_type = remove_cvref_t>; @@ -655,23 +676,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// [alg.req.ind.move], concept `indirectly_movable` template - concept indirectly_movable = readable<_In> - && writable<_Out, iter_rvalue_reference_t<_In>>; + concept indirectly_movable = indirectly_readable<_In> + && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; template concept indirectly_movable_storable = indirectly_movable<_In, _Out> - && writable<_Out, iter_value_t<_In>> && movable> + && indirectly_writable<_Out, iter_value_t<_In>> + && movable> && constructible_from, iter_rvalue_reference_t<_In>> && assignable_from&, iter_rvalue_reference_t<_In>>; /// [alg.req.ind.copy], concept `indirectly_copyable` template - concept indirectly_copyable = readable<_In> - && writable<_Out, iter_reference_t<_In>>; + concept indirectly_copyable = indirectly_readable<_In> + && indirectly_writable<_Out, iter_reference_t<_In>>; template concept indirectly_copyable_storable = indirectly_copyable<_In, _Out> - && writable<_Out, const iter_value_t<_In>&> + && indirectly_writable<_Out, const iter_value_t<_In>&> && copyable> && constructible_from, iter_reference_t<_In>> && assignable_from&, iter_reference_t<_In>>; @@ -692,12 +714,12 @@ namespace ranges }; template - constexpr iter_value_t> + constexpr iter_value_t<_Xp> __iter_exchange_move(_Xp&& __x, _Yp&& __y) - noexcept(noexcept(iter_value_t>(iter_move(__x))) + noexcept(noexcept(iter_value_t<_Xp>(iter_move(__x))) && noexcept(*__x = iter_move(__y))) { - iter_value_t> __old_value(iter_move(__x)); + iter_value_t<_Xp> __old_value(iter_move(__x)); *__x = iter_move(__y); return __old_value; } @@ -712,8 +734,9 @@ namespace ranges if constexpr (__adl_iswap<_Tp, _Up>) return noexcept(iter_swap(std::declval<_Tp>(), std::declval<_Up>())); - else if constexpr (readable<_Tp> && readable<_Up> - && swappable_with, iter_reference_t<_Up>>) + else if constexpr (indirectly_readable<_Tp> + && indirectly_readable<_Up> + && swappable_with, iter_reference_t<_Up>>) return noexcept(ranges::swap(*std::declval<_Tp>(), *std::declval<_Up>())); else @@ -725,8 +748,8 @@ namespace ranges public: template requires __adl_iswap<_Tp, _Up> - || (readable> - && readable> + || (indirectly_readable> + && indirectly_readable> && swappable_with, iter_reference_t<_Up>>) || (indirectly_movable_storable<_Tp, _Up> && indirectly_movable_storable<_Up, _Tp>) @@ -736,8 +759,9 @@ namespace ranges { if constexpr (__adl_iswap<_Tp, _Up>) iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2)); - else if constexpr (readable<_Tp> && readable<_Up> - && swappable_with, iter_reference_t<_Up>>) + else if constexpr (indirectly_readable<_Tp> + && indirectly_readable<_Up> + && swappable_with, iter_reference_t<_Up>>) ranges::swap(*__e1, *__e2); else *__e1 = __iter_exchange_move(__e2, __e1); @@ -754,8 +778,9 @@ namespace ranges /// [alg.req.ind.swap], concept `indirectly_swappable` template - concept indirectly_swappable = readable<_I1> && readable<_I2> - && requires(_I1& __i1, _I2& __i2) + concept indirectly_swappable + = indirectly_readable<_I1> && indirectly_readable<_I2> + && requires(const _I1 __i1, const _I2 __i2) { ranges::iter_swap(__i1, __i1); ranges::iter_swap(__i2, __i2); diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index 927c83c55b7..e065ff2a974 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -1219,7 +1219,9 @@ namespace ranges template _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 - requires writable<_Out, - indirect_result_t<_Fp&, projected, - _Proj>>> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj>>> constexpr unary_transform_result, _Out> transform(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) { @@ -1268,8 +1270,10 @@ 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>, - projected<_Iter2, _Proj2>>> + 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, _Out __result, _Fp __binary_op, @@ -1286,11 +1290,10 @@ namespace ranges template - requires writable<_Out, indirect_result_t<_Fp&, - projected, - _Proj1>, - projected, - _Proj2>>> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj1>, + projected, _Proj2>>> constexpr binary_transform_result, safe_iterator_t<_Range2>, _Out> transform(_Range1&& __r1, _Range2&& __r2, _Out __result, @@ -1304,9 +1307,9 @@ namespace ranges template _Sent, typename _Tp1, typename _Tp2, typename _Proj = identity> - requires writable<_Iter, const _Tp2&> && - indirect_binary_predicate, const _Tp1*> + requires indirectly_writable<_Iter, const _Tp2&> + && indirect_binary_predicate, + const _Tp1*> constexpr _Iter replace(_Iter __first, _Sent __last, const _Tp1& __old_value, const _Tp2& __new_value, @@ -1320,10 +1323,10 @@ namespace ranges template - requires writable, const _Tp2&> && - indirect_binary_predicate, _Proj>, - const _Tp1*> + requires indirectly_writable, const _Tp2&> + && indirect_binary_predicate, _Proj>, + const _Tp1*> constexpr safe_iterator_t<_Range> replace(_Range&& __r, const _Tp1& __old_value, const _Tp2& __new_value, @@ -1336,7 +1339,7 @@ namespace ranges template _Sent, typename _Tp, typename _Proj = identity, indirect_unary_predicate> _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, _Proj>> _Pred> - requires writable, const _Tp&> + requires indirectly_writable, 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 - 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 _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,10 +1578,10 @@ namespace ranges } template - requires permutable> && - indirect_binary_predicate, _Proj>, - const _Tp*> + requires permutable> + && indirect_binary_predicate, _Proj>, + const _Tp*> constexpr safe_subrange_t<_Range> remove(_Range&& __r, const _Tp& __value, _Proj __proj = {}) { diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 46804656801..4e70672924b 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1417,7 +1417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; template - concept __common_iter_has_arrow = readable + concept __common_iter_has_arrow = indirectly_readable && (requires(const _It& __it) { __it.operator->(); } || is_reference_v> || constructible_from, iter_reference_t<_It>>); diff --git a/libstdc++-v3/include/ext/pointer.h b/libstdc++-v3/include/ext/pointer.h index 02d3e60169f..aef622e2e23 100644 --- a/libstdc++-v3/include/ext/pointer.h +++ b/libstdc++-v3/include/ext/pointer.h @@ -47,7 +47,7 @@ # include #endif #if __cplusplus > 201703L -# include // for readable_traits +# include // for indirectly_readable_traits #endif namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) @@ -598,11 +598,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #if __cpp_lib_concepts - template - struct readable_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>> + template + 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 diff --git a/libstdc++-v3/testsuite/24_iterators/associated_types/readable.traits.cc b/libstdc++-v3/testsuite/24_iterators/associated_types/readable.traits.cc index 724e6eaa02a..b503b0cdc1e 100644 --- a/libstdc++-v3/testsuite/24_iterators/associated_types/readable.traits.cc +++ b/libstdc++-v3/testsuite/24_iterators/associated_types/readable.traits.cc @@ -24,9 +24,9 @@ struct none; template concept has_readable_traits_type - = requires { typename std::readable_traits::value_type; }; + = requires { typename std::indirectly_readable_traits::value_type; }; -// Check std::readable_traits::value_type is U (or doesn't exist). +// Check std::indirectly_readable_traits::value_type is U (or doesn't exist). template concept check_readable_traits = (has_readable_traits_type != std::same_as); @@ -62,7 +62,7 @@ static_assert( check_readable_traits ); struct E { }; template<> - struct std::readable_traits { using value_type = long; }; + struct std::indirectly_readable_traits { using value_type = long; }; static_assert( check_readable_traits ); static_assert( check_readable_traits ); @@ -103,7 +103,7 @@ static_assert( check_alias::value_type> ); struct G { }; template<> - struct std::readable_traits { using value_type = G; }; + struct std::indirectly_readable_traits { using value_type = G; }; template<> struct std::iterator_traits { using value_type = int; }; // iterator_traits is specialized, so use its value_type. @@ -111,7 +111,7 @@ static_assert( check_alias::value_type> ); struct H { }; template<> - struct std::readable_traits { using value_type = H; }; + struct std::indirectly_readable_traits { using value_type = H; }; template<> struct std::iterator_traits { @@ -128,8 +128,8 @@ struct I using value_type = I; }; // iterator_traits is not specialized, and no standard specialization -// matches, so use readable_traits. -static_assert( check_alias::value_type> ); +// matches, so use indirectly_readable_traits. +static_assert( check_alias::value_type> ); struct J { diff --git a/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc b/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc index 3f01677856a..f6e4afb7dc9 100644 --- a/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc +++ b/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc @@ -29,9 +29,11 @@ static_assert(std::same_as&>()), int&>); struct X { using value_type = char*; - char* const& operator*() &; + char* const& operator*() const; }; -static_assert( std::readable ); +static_assert( std::indirectly_readable ); +static_assert( std::indirectly_readable ); +static_assert( std::indirectly_readable ); static_assert(std::same_as::value_type, char*>); static_assert(std::same_as&>()), char* const&>);