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
> >
> >
>

Reply via email to