On Wed, 9 Oct 2024 at 14:02, Patrick Palka <ppa...@redhat.com> wrote: > > On Mon, 7 Oct 2024, Patrick Palka wrote: > > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk only? > > This doesn't seem worth backporting since there should be no > > behavior change. > > > > -- >8 -- > > > > This implements the library changes in P0849R8 "auto(x): decay-copy > > in the language" which consist of replacing most uses of the > > exposition-only function decay-copy with auto(x) throughout the library > > wording. > > > > Note the main difference between the two is that decay-copy materializes > > its argument whereas auto(x) doesn't, and so the latter is a no-op when > > its argument is a prvalue. Effectively the former could introduce an > > unnecessary move constructor call in some contexts. In C++20 and earlier > > we could emulate auto(x) with decay_t<decltype((x))>(x). > > I should note this patch is treating this paper as a DR against C++20, > which should be fine since there should be no behavior change in > practice (especially in light of LWG 3724 which constrains decay-copy > to make it SFINAE-friendly).
Yes, that seems fine. OK for trunk, thanks. > > > > > After this paper the only remaining uses of decay-copy in the library > > are in the specification of some range adaptors. In our implementation > > of those range adaptors I believe decay-copy is already implied which > > is why we don't mirror the wording and use __decay_copy explicitly. So > > since it's apparently no longer needed this patch goes ahead and removes > > __decay_copy. > > > > libstdc++-v3/ChangeLog: > > > > * c++config (_GLIBCXX_AUTO_CAST): Define. > > * include/bits/iterator_concepts.h (_Decay_copy, __decay_copy): > > Remove. > > (__member_begin, __adl_begin): Use _GLIBCXX_AUTO_CAST instead of > > __decay_copy as per P0849R8. > > * include/bits/ranges_base.h (_Begin): Likewise. > > (__member_end, __adl_end, _End): Likewise. > > (__member_rbegin, __adl_rbegin, _RBegin): Likewise. > > (__member_rend, __adl_rend, _Rend): Likewise. > > (__member_size, __adl_size, _Size): Likewise. > > (_Data): Likewise. > > --- > > libstdc++-v3/include/bits/c++config | 6 +++ > > libstdc++-v3/include/bits/iterator_concepts.h | 13 +----- > > libstdc++-v3/include/bits/ranges_base.h | 40 +++++++++---------- > > 3 files changed, 28 insertions(+), 31 deletions(-) > > > > diff --git a/libstdc++-v3/include/bits/c++config > > b/libstdc++-v3/include/bits/c++config > > index 29d795f687c..fdbf90e28fc 100644 > > --- a/libstdc++-v3/include/bits/c++config > > +++ b/libstdc++-v3/include/bits/c++config > > @@ -265,6 +265,12 @@ > > #define _GLIBCXX_NOEXCEPT_QUAL > > #endif > > > > +#if __cpp_auto_cast > > +# define _GLIBCXX_AUTO_CAST(X) auto(X) > > +#else > > +# define _GLIBCXX_AUTO_CAST(X) ::std::__decay_t<decltype((X))>(X) > > +#endif > > + > > // Macro for extern template, ie controlling template linkage via use > > // of extern keyword on template declaration. As documented in the g++ > > // manual, it inhibits all implicit instantiations and is used > > diff --git a/libstdc++-v3/include/bits/iterator_concepts.h > > b/libstdc++-v3/include/bits/iterator_concepts.h > > index 490a362cdf1..0fcfed56737 100644 > > --- a/libstdc++-v3/include/bits/iterator_concepts.h > > +++ b/libstdc++-v3/include/bits/iterator_concepts.h > > @@ -1003,19 +1003,10 @@ namespace ranges > > { > > using std::__detail::__class_or_enum; > > > > - struct _Decay_copy final > > - { > > - template<typename _Tp> > > - constexpr decay_t<_Tp> > > - operator()(_Tp&& __t) const > > - noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) > > - { return std::forward<_Tp>(__t); } > > - } inline constexpr __decay_copy{}; > > - > > template<typename _Tp> > > concept __member_begin = requires(_Tp& __t) > > { > > - { __decay_copy(__t.begin()) } -> input_or_output_iterator; > > + { _GLIBCXX_AUTO_CAST(__t.begin()) } -> input_or_output_iterator; > > }; > > > > // Poison pill so that unqualified lookup doesn't find std::begin. > > @@ -1025,7 +1016,7 @@ namespace ranges > > concept __adl_begin = __class_or_enum<remove_reference_t<_Tp>> > > && requires(_Tp& __t) > > { > > - { __decay_copy(begin(__t)) } -> input_or_output_iterator; > > + { _GLIBCXX_AUTO_CAST(begin(__t)) } -> input_or_output_iterator; > > }; > > > > // Simplified version of std::ranges::begin that only supports lvalues, > > diff --git a/libstdc++-v3/include/bits/ranges_base.h > > b/libstdc++-v3/include/bits/ranges_base.h > > index cb2eba1f841..80ff1e300ce 100644 > > --- a/libstdc++-v3/include/bits/ranges_base.h > > +++ b/libstdc++-v3/include/bits/ranges_base.h > > @@ -115,9 +115,9 @@ namespace ranges > > if constexpr (is_array_v<remove_reference_t<_Tp>>) > > return true; > > else if constexpr (__member_begin<_Tp>) > > - return noexcept(__decay_copy(std::declval<_Tp&>().begin())); > > + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().begin())); > > else > > - return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); > > + return noexcept(_GLIBCXX_AUTO_CAST(begin(std::declval<_Tp&>()))); > > } > > > > public: > > @@ -142,7 +142,7 @@ namespace ranges > > template<typename _Tp> > > concept __member_end = requires(_Tp& __t) > > { > > - { __decay_copy(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>; > > + { _GLIBCXX_AUTO_CAST(__t.end()) } -> > > sentinel_for<__range_iter_t<_Tp>>; > > }; > > > > // Poison pill so that unqualified lookup doesn't find std::end. > > @@ -152,7 +152,7 @@ namespace ranges > > concept __adl_end = __class_or_enum<remove_reference_t<_Tp>> > > && requires(_Tp& __t) > > { > > - { __decay_copy(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>; > > + { _GLIBCXX_AUTO_CAST(end(__t)) } -> > > sentinel_for<__range_iter_t<_Tp>>; > > }; > > > > struct _End > > @@ -165,9 +165,9 @@ namespace ranges > > if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) > > return true; > > else if constexpr (__member_end<_Tp>) > > - return noexcept(__decay_copy(std::declval<_Tp&>().end())); > > + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().end())); > > else > > - return noexcept(__decay_copy(end(std::declval<_Tp&>()))); > > + return noexcept(_GLIBCXX_AUTO_CAST(end(std::declval<_Tp&>()))); > > } > > > > public: > > @@ -192,7 +192,7 @@ namespace ranges > > template<typename _Tp> > > concept __member_rbegin = requires(_Tp& __t) > > { > > - { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; > > + { _GLIBCXX_AUTO_CAST(__t.rbegin()) } -> input_or_output_iterator; > > }; > > > > void rbegin() = delete; > > @@ -201,7 +201,7 @@ namespace ranges > > concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>> > > && requires(_Tp& __t) > > { > > - { __decay_copy(rbegin(__t)) } -> input_or_output_iterator; > > + { _GLIBCXX_AUTO_CAST(rbegin(__t)) } -> input_or_output_iterator; > > }; > > > > template<typename _Tp> > > @@ -219,9 +219,9 @@ namespace ranges > > _S_noexcept() > > { > > if constexpr (__member_rbegin<_Tp>) > > - return noexcept(__decay_copy(std::declval<_Tp&>().rbegin())); > > + return > > noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rbegin())); > > else if constexpr (__adl_rbegin<_Tp>) > > - return noexcept(__decay_copy(rbegin(std::declval<_Tp&>()))); > > + return noexcept(_GLIBCXX_AUTO_CAST(rbegin(std::declval<_Tp&>()))); > > else > > { > > if constexpr (noexcept(_End{}(std::declval<_Tp&>()))) > > @@ -254,7 +254,7 @@ namespace ranges > > template<typename _Tp> > > concept __member_rend = requires(_Tp& __t) > > { > > - { __decay_copy(__t.rend()) } > > + { _GLIBCXX_AUTO_CAST(__t.rend()) } > > -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>; > > }; > > > > @@ -264,7 +264,7 @@ namespace ranges > > concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>> > > && requires(_Tp& __t) > > { > > - { __decay_copy(rend(__t)) } > > + { _GLIBCXX_AUTO_CAST(rend(__t)) } > > -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>; > > }; > > > > @@ -276,9 +276,9 @@ namespace ranges > > _S_noexcept() > > { > > if constexpr (__member_rend<_Tp>) > > - return noexcept(__decay_copy(std::declval<_Tp&>().rend())); > > + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rend())); > > else if constexpr (__adl_rend<_Tp>) > > - return noexcept(__decay_copy(rend(std::declval<_Tp&>()))); > > + return noexcept(_GLIBCXX_AUTO_CAST(rend(std::declval<_Tp&>()))); > > else > > { > > if constexpr (noexcept(_Begin{}(std::declval<_Tp&>()))) > > @@ -312,7 +312,7 @@ namespace ranges > > concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>> > > && requires(_Tp& __t) > > { > > - { __decay_copy(__t.size()) } -> __detail::__is_integer_like; > > + { _GLIBCXX_AUTO_CAST(__t.size()) } -> __detail::__is_integer_like; > > }; > > > > void size() = delete; > > @@ -322,7 +322,7 @@ namespace ranges > > && !disable_sized_range<remove_cvref_t<_Tp>> > > && requires(_Tp& __t) > > { > > - { __decay_copy(size(__t)) } -> __detail::__is_integer_like; > > + { _GLIBCXX_AUTO_CAST(size(__t)) } -> __detail::__is_integer_like; > > }; > > > > template<typename _Tp> > > @@ -347,9 +347,9 @@ namespace ranges > > if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) > > return true; > > else if constexpr (__member_size<_Tp>) > > - return noexcept(__decay_copy(std::declval<_Tp&>().size())); > > + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().size())); > > else if constexpr (__adl_size<_Tp>) > > - return noexcept(__decay_copy(size(std::declval<_Tp&>()))); > > + return noexcept(_GLIBCXX_AUTO_CAST(size(std::declval<_Tp&>()))); > > else if constexpr (__sentinel_size<_Tp>) > > return noexcept(_End{}(std::declval<_Tp&>()) > > - _Begin{}(std::declval<_Tp&>())); > > @@ -459,7 +459,7 @@ namespace ranges > > template<typename _Tp> > > concept __member_data = requires(_Tp& __t) > > { > > - { __decay_copy(__t.data()) } -> __pointer_to_object; > > + { _GLIBCXX_AUTO_CAST(__t.data()) } -> __pointer_to_object; > > }; > > > > template<typename _Tp> > > @@ -473,7 +473,7 @@ namespace ranges > > _S_noexcept() > > { > > if constexpr (__member_data<_Tp>) > > - return noexcept(__decay_copy(std::declval<_Tp&>().data())); > > + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().data())); > > else > > return noexcept(_Begin{}(std::declval<_Tp&>())); > > } > > -- > > 2.47.0.rc1.33.g90fe3800b9 > > > > >