本篇介绍
本篇继续C 的模版介绍
std::enable_if<>
enable_if<> 的作用是满足条件后可以使用模版推导,基于SFINAE(substitution failure is not an error), 这样可以按照条件控制是否使用模版。
代码语言:javascript复制template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;
查看下面的例子:
代码语言:javascript复制 template<typename T>
std::enable_if_t<(sizeof(T) > 4)>
foo() {
}
就是在 T的大小超过4之后,就推导出void fun() {}
有时候也可以这样写:
template<typename T,
typename = std::enable_if_t<(sizeof(T) > 4)>>
void foo() { }
在C 20中,也可以不使用enable_if, 通过requires 和concept关键字即可:
代码语言:javascript复制template<typename STR>
requires std::is_convertible_v<STR,std::string>
Person(STR&& n) : name(std::forward<STR>(n)) {
}
template<typename T>
concept ConvertibleToString = std::is_convertible_v<T,std::string>;
编译时的if
c 17支持编译时的if,这样就可以在编译态作为开关,如下所示:
代码语言:javascript复制 template<typename T, typename... Types>
void print (T const& firstArg, Types const&... args)
{
std::cout << firstArg << ’n’;
if constexpr(sizeof...(args) > 0) {
print(args...); // code only available if sizeof...(args)>0 (since C 17) }
}
enable_shared_from_this
遇到需要用this 构造shared_ptr的时候都需要继承一下 enable_shared_from_this, 原因是什么呢? 看下源码
代码语言:javascript复制template<class _Tp>
class _LIBCPP_TEMPLATE_VIS enable_shared_from_this
{
mutable weak_ptr<_Tp> __weak_this_;
protected:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
enable_shared_from_this() _NOEXCEPT {}
_LIBCPP_INLINE_VISIBILITY
enable_shared_from_this(enable_shared_from_this const&) _NOEXCEPT {}
_LIBCPP_INLINE_VISIBILITY
enable_shared_from_this& operator=(enable_shared_from_this const&) _NOEXCEPT
{return *this;}
_LIBCPP_INLINE_VISIBILITY
~enable_shared_from_this() {}
public:
_LIBCPP_INLINE_VISIBILITY
shared_ptr<_Tp> shared_from_this()
{return shared_ptr<_Tp>(__weak_this_);}
_LIBCPP_INLINE_VISIBILITY
shared_ptr<_Tp const> shared_from_this() const
{return shared_ptr<const _Tp>(__weak_this_);}
#if _LIBCPP_STD_VER > 14
_LIBCPP_INLINE_VISIBILITY
weak_ptr<_Tp> weak_from_this() _NOEXCEPT
{ return __weak_this_; }
_LIBCPP_INLINE_VISIBILITY
weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT
{ return __weak_this_; }
#endif // _LIBCPP_STD_VER > 14
template <class _Up> friend class shared_ptr;
};
这里面有一个_weak_this, 可是没有赋值的地方,那是哪儿赋值的呢?看到有一个friend shared_ptr。看下他的实现:
代码语言:javascript复制shared_ptr<_Tp>::shared_ptr(_Yp* __p,
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
: __ptr_(__p)
{
unique_ptr<_Yp> __hold(__p);
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, _AllocT > _CntrlBlk;
__cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), _AllocT());
__hold.release();
__enable_weak_this(__p, __p);
}
__enable_weak_this(const enable_shared_from_this<_Yp>* __e,
_OrigPtr* __ptr) _NOEXCEPT
{
typedef typename remove_cv<_Yp>::type _RawYp;
if (__e && __e->__weak_this_.expired())
{
__e->__weak_this_ = shared_ptr<_RawYp>(*this,
const_cast<_RawYp*>(static_cast<const _Yp*>(__ptr)));
}
}
看到这儿就可以得出以下结论:
- shared_from_this本质上是通过一个弱指针来感知this是否有效,并且利用弱指针来创建shared_ptr
- 弱指针是在首次使用智能指针创建对应对象的时候初始化的,那么就需要要求调用shared_from_this前,该对象已经被智能指针持有了。