C++模版笔记(2)

2022-10-25 16:52:25 浏览数 (1)

本篇介绍

本篇继续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() {} 有时候也可以这样写:

代码语言:javascript复制
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)));
            }
        }

看到这儿就可以得出以下结论:

  1. shared_from_this本质上是通过一个弱指针来感知this是否有效,并且利用弱指针来创建shared_ptr
  2. 弱指针是在首次使用智能指针创建对应对象的时候初始化的,那么就需要要求调用shared_from_this前,该对象已经被智能指针持有了。

0 人点赞