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.