I analyse this question from code in STL:
auto t(std::make_shared());
the code line construct a shared_ptr;First we dive into the make_shared function
// FUNCTION TEMPLATE make_shared
template<class _Ty,
class... _Types>
NODISCARD inline shared_ptr<_Ty> make_shared(_Types&&... _Args)
{ // make a shared_ptr
const auto _Rx = new _Ref_count_obj<_Ty>(_STD forward<_Types>(_Args)...);
shared_ptr<_Ty> _Ret;
_Ret._Set_ptr_rep_and_enable_shared(_Rx->_Getptr(), _Rx);
return (_Ret);
}
caution: we dive into function _Ret.Set_ptr_rep_and_enable_shared.And we can see follows:
template<class _Ux>
void _Set_ptr_rep_and_enable_shared(_Ux * _Px, _Ref_count_base * _Rx)
{ // take ownership of _Px
this->_Set_ptr_rep(_Px, _Rx);
_Enable_shared_from_this(*this, _Px);
}
So we find function _Enable_shared_from_this ,the go on:
template<class _Other,
class _Yty>
void _Enable_shared_from_this(const shared_ptr<_Other>& _This, _Yty * _Ptr)
{ // possibly enable shared_from_this
_Enable_shared_from_this1(_This, _Ptr, _Conjunction_t<
negation<is_array<_Other>>,
negation<is_volatile<_Yty>>,
_Can_enable_shared<_Yty>>{});
}
We find a key point: _Can_enable_shared<_Yty>
template<class _Yty,
class = void>
struct _Can_enable_shared
: false_type
{ // detect unambiguous and accessible inheritance from enable_shared_from_this
};
template<class _Yty>
struct _Can_enable_shared<_Yty, void_t<typename _Yty::_Esft_type>>
: is_convertible<remove_cv_t<_Yty> *, typename _Yty::_Esft_type *>::type
{ // is_convertible is necessary to verify unambiguous inheritance
};
we find only _Yty has _Esft_type and _Yty can be converted to _Esft_type, can _Yty can be enable_shared(If you want to know more, that's to see set weak_ptr in _Yty, or you may get bad_weak_ptr error when you use shared_from_this).
So what _Esft_type is?
template<class _Ty>
class enable_shared_from_this
{ // provide member functions that create shared_ptr to this
public:
using _Esft_type = enable_shared_from_this;
...
}
so _Esft_type just mean enable_shared_from_this<_Ty>, so if you use private inherit, outside not only cann't see _Esft_type and _Yt cann't be converted to _Esft_type. So weak_ptr cann't be set so bad_weak_ptr may be invoked.
So outside need know the existence of _Esft_type, so when shared_ptr is constructed, weak_ptr of shared_test can also be set.