https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114356

            Bug ID: 114356
           Summary: std::shared_ptr constructor constraints give poor
                    diagnostics
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Keywords: diagnostic
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

We avoid repeating constructor constraints by deferring to the base class:

      template<typename... _Args>
        using _Constructible = typename enable_if<
          is_constructible<__shared_ptr<_Tp>, _Args...>::value
        >::type;

      template<typename _Yp, typename = _Constructible<_Yp*>>
        explicit
        shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }

However this means that the diagnostics are unhelpful, because all you get is
an error saying the enable_if<is_constructible<...>> check failed:

/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:223:9: note:
candidate: 'template<class _Yp, class> std::shared_ptr<_Tp>::shared_ptr(_Yp*)
[with <template-parameter-2-2> = _Yp; _Tp = A]'
  223 |         shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
      |         ^~~~~~~~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:223:9: note:  
template argument deduction/substitution failed:
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h: In substitution of
'template<class _Tp> template<class ... _Args> using
std::shared_ptr<_Tp>::_Constructible = typename
std::enable_if<std::is_constructible<std::__shared_ptr<_Tp>, _Args
...>::value>::type [with _Args = {B*}; _Tp = A]':
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:221:30:   required
from here
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:223:9: note:   221 | 
     template<typename _Yp, typename = _Constructible<_Yp*>>
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:223:9: note:       | 
                            ^~~~~~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:187:15: error: no
type named 'type' in 'struct std::enable_if<false, void>'
  187 |         using _Constructible = typename enable_if<
      |               ^~~~~~~~~~~~~~


If we do repeat the constraints in the derived class, and use concepts to do
it, the error is ... still terrible. We output every constructor candidate, all
19 of them, in the reverse order they're declared in (why is that?!) but at
least somewhere in the middle is:

/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:224:9: note:
candidate: 'template<class _Yp>  requires  __sp_is_constructible<_Tp, _Yp>
std::shared_ptr<_Tp>::shared_ptr(_Yp*) [with _Tp = A]'
  224 |         shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
      |         ^~~~~~~~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:224:9: note:  
template argument deduction/substitution failed:
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:224:9: note:
constraints not satisfied
In file included from
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:53:
cons.cc: In substitution of 'template<class _Yp>  requires 
__sp_is_constructible<_Tp, _Yp> std::shared_ptr<A>::shared_ptr(_Yp*) [with _Yp
= A]':
cons.cc:8:28:   required from here
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:224:9: note:     8 |
std::shared_ptr<A> sp(new B);
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:224:9: note:       | 
                          ^
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1285:13:  
required for the satisfaction of '__sp_is_constructible<_Tp, _Yp>' [with _Tp =
A; _Yp = B]
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1287:11: note:
no operand of the disjunction is satisfied
 1286 |       = __sp_is_constructible_non_array<_Tp, _Yp>
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1287 |           || __sp_is_constructible_array<_Tp, _Yp>;
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1286:9: note:
the operand '__sp_is_constructible_non_array<_Tp, _Yp>' is unsatisfied because
 1286 |       = __sp_is_constructible_non_array<_Tp, _Yp>
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1287 |           || __sp_is_constructible_array<_Tp, _Yp>;
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1266:13:  
required for the satisfaction of '__sp_is_constructible_non_array<_Tp, _Yp>'
[with _Tp = A; _Yp = B]
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1285:13:  
required for the satisfaction of '__sp_is_constructible<_Tp, _Yp>' [with _Tp =
A; _Yp = B]
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1268:14: note:
the expression 'is_convertible_v<_Yp*, _Tp*> [with _Yp = B; _Tp = A]' evaluated
to 'false'
 1268 |           && is_convertible_v<_Yp*, _Tp*>;
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1287:14: note:
the operand '__sp_is_constructible_array<_Tp, _Yp>' is unsatisfied because
 1286 |       = __sp_is_constructible_non_array<_Tp, _Yp>
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1287 |           || __sp_is_constructible_array<_Tp, _Yp>;
      |           ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1279:13:  
required for the satisfaction of '__sp_is_constructible_array<_Tp, _Yp>' [with
_Tp = A; _Yp = B]
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1285:13:  
required for the satisfaction of '__sp_is_constructible<_Tp, _Yp>' [with _Tp =
A; _Yp = B]
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr_base.h:1280:9: note:
the expression 'is_array_v<_Yp> [with _Yp = B]' evaluated to 'false'
 1280 |       = is_array_v<_Yp> && requires (_Yp* __p) { delete[] __p; }
      |         ^~~~~~~~~~~~~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/shared_ptr.h:545:7: note:
candidate: 'std::shared_ptr<_Tp>::shared_ptr(const std::weak_ptr<_Tp>&,
std::nothrow_t) [with _Tp = A]'


This is barely readable, but somewhere in the middle is the actual problem:

 1268 |           && is_convertible_v<_Yp*, _Tp*>;


You have a better chance to debug the error with this info than with the result
with current trunk, which basically only tells you the construction doesn't
work because the type's not constructible.

Reply via email to