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

Reply via email to