On Wed, May 6, 2026 at 11:01 AM Jonathan Wakely <[email protected]> wrote:

> On Wed, 6 May 2026 at 08:57, Tomasz Kaminski <[email protected]> wrote:
> >
> >
> >
> > On Tue, May 5, 2026 at 5:04 PM Jonathan Wakely <[email protected]>
> wrote:
> >>
> >> Clang 10 added support for concepts, so we no longer need to support
> >> C++20 compilers that don't define __cpp_concepts.
> >>
> >> libstdc++-v3/ChangeLog:
> >>
> >>         * include/bits/shared_ptr.h (_UnboundedArray, _BoundedArray)
> >>         (_NotUnboundedArray): Remove fallback definition for C++20
> >>         compilers that don't define __cpp_concepts.
> >>         * include/bits/shared_ptr_base.h (_Sp_counted_ptr_inplace):
> >>         Remove fallback declaration of _Sp_overwrite_tag partial
> >>         specialization.
> >> ---
> >>
> >> Tested x86_64-linux.
> >>
> >>  libstdc++-v3/include/bits/shared_ptr.h      | 18 ------------------
> >>  libstdc++-v3/include/bits/shared_ptr_base.h |  5 -----
> >>  2 files changed, 23 deletions(-)
> >>
> >> diff --git a/libstdc++-v3/include/bits/shared_ptr.h
> b/libstdc++-v3/include/bits/shared_ptr.h
> >> index fd00384df223..ada32d3d3cb9 100644
> >> --- a/libstdc++-v3/include/bits/shared_ptr.h
> >> +++ b/libstdc++-v3/include/bits/shared_ptr.h
> >> @@ -114,38 +114,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >>
> >>  #if __glibcxx_shared_ptr_arrays >= 201707L
> >>    // Constraint for overloads taking array types with unknown bound,
> U[].
> >> -#if __cpp_concepts
> >>    template<typename _Tp>
> >>      requires is_array_v<_Tp> && (extent_v<_Tp> == 0)
> >>      using _UnboundedArray = _Tp;
> >
> > Could we replace this constrained alias with requires/concept on the
> function?
> > that are using it? This version was always deductible, so shouldn't make
> difference.
>
> I wanted to do that, but just above this diff we have:
>
>   // Constraint for overloads taking non-array types.
> #if __cpp_concepts && __glibcxx_type_trait_variable_templates
>   template<typename _Tp>
>     requires (!is_array_v<_Tp>)
>     using _NonArray = _Tp;
> #else
>   template<typename _Tp>
>     using _NonArray = __enable_if_t<!is_array<_Tp>::value, _Tp>;
> #endif
>
> That *can't* use a requires-clause, it has to continue using a
> constrained alias for C++11 mode.
>
> That means that std::make_shared and std::allocate_shared are
> constrained using the alias:
>
>   template<typename _Yp, typename _Alloc, typename... _Args>
>     friend shared_ptr<_NonArray<_Yp>>
>     allocate_shared(const _Alloc&, _Args&&...);
>
>   template<typename _Yp, typename... _Args>
>     friend shared_ptr<_NonArray<_Yp>>
>     make_shared(_Args&&...);
>
> So for consistency I didn't want to change how the C++20 overloads are
> defined:
>
>   template<typename _Yp, typename _Alloc>
>     friend shared_ptr<_UnboundedArray<_Yp>>
>     allocate_shared(const _Alloc&, size_t);
>
>   template<typename _Yp>
>     friend shared_ptr<_UnboundedArray<_Yp>>
>     make_shared(size_t);
>
> We could do it for the C++20 ones. I think it would still work
> correctly to have the C++11 overloads constrained using the alias and
> the later ones constrained using a requires-clause. The conditions
> that enable each overload are mutually exclusive, so there would be no
> concerns about the interaction between the different types of
> constraints on overload resolution. There would still be exactly one
> viable candidate for any given call.
>
> For make_shared_for_overwrite we don't have to worry about the
> interaction with the C++11 overload, because there is no C++11
> overload. So we could change that to use a requires-clause, but it
> would still look inconsistent with the related (not "_for_overwrite")
> function templates.
>
> Also, because these make_shared* and allocate_shared* function
> templates are all friends, if we use a requires-clause it needs to be
> repeated in two places.
>
> So yes, it would be possible. I considered it, and decided to keep the
> aliases (at least for now).
>
That makes sense, thanks for the detailed explanation.

Reply via email to