【问题标题】:How does shared_ptr<T> detect that T derives from enable_shared_from_this<T>?shared_ptr<T> 如何检测 T 派生自 enable_shared_from_this<T>?
【发布时间】:2014-10-11 17:39:02
【问题描述】:

我试图通过从头实现 shared_ptr 来了解它是如何工作的,但我不知道如何检测 T 的基类。

我尝试过使用 is_base_of(),但它给出了一个 const 值,我不能将它与 if 语句一起使用来设置对象的内部weak_ptr。

我的想法是这样的:

template <class T>
class shared_ptr
{
    shared_ptr(T* ptr)
    {
        ...
    }

    shared_ptr(enable_shared_from_this<T>* ptr)
    {
        ...

        Ptr->m_this = weak_ptr<T>(this);
    }
};

但到目前为止还没有运气。 Boost 和 VC++ 的实现对我来说太混乱了,我正在寻找一个简单的解释。

Here 它说

std::shared_ptr 的构造函数检测到 enable_shared_from_this 基的存在,并将新创建的 std::shared_ptr 分配给内部存储的弱引用。

是的,怎么做?

【问题讨论】:

    标签: c++ boost std shared-ptr enable-shared-from-this


    【解决方案1】:

    简单——使用模板参数推导!这是世界上所有问题的解决方案,但您已经知道了:) 基于 boost 解决您的问题的方式的解决方案如下。我们创建了一个模板化的帮助类,它实际上处理了构造的细节。

    template <class T>
    class shared_ptr
    {
        shared_ptr(T* ptr)
        {
            magic_construct(this, ptr, ptr);
        }
    };
    
    template <class X, class Y, class Z>
    void magic_construct(shared_ptr<X>* sp, Y* rp, enable_shared_from_this<Z>* shareable)
    {
    //Do the weak_ptr handling here
    }
    
    void magic_construct(...)//This is the default case
    {
    //This is the case where you have no inheritance from enable_shared_from_this
    }
    

    【讨论】:

    • 为什么只有template &lt;class Z&gt; magic_construct(enable_shared_from_this&lt;Z&gt;* share) 还不够?为什么我需要sprp 参数?
    • 私有继承会发生什么?
    【解决方案2】:

    一种选择是基于函数模板重载。

    这是一个简化的解决方案: 我们有两个类 A 和 B。类 A 派生自 H。 函数is_derived_from_h被重载,可以用来检测某个类X是否派生自H。

    #include <stdlib.h>
    #include <iostream>
    
    class H {};
    class A: public H {};
    class B {};
    
    // (1)
    template <typename X>
    void is_derived_from_h(X* px, H* ph) {
      std::cout << "TRUE" << std::endl;
    }
    
    // (2)
    void is_derived_from_h(...) {
      std::cout << "FALSE" << std::endl;
    }
    
    int main(int argc, char* argv[]) {
    
      A* pa = new A;
      B* pb = new B;
    
      is_derived_from_h(pa, pa); // (1) is selected, the closest overload
      is_derived_from_h(pb, pb); // (2) is selected, (1) is not viable
    
      delete pa;
      delete pb;
    
      return EXIT_SUCCESS;
    }
    

    输出:

    TRUE
    FALSE
    

    如果是 Boost,请跟踪以下调用:

    shared_ptr( Y * p )
    ->
    boost::detail::sp_pointer_construct( this, p, pn );
      ->
    boost::detail::sp_enable_shared_from_this( ppx, p, p );
    

    sp_enable_shared_from_this 有多个版本。根据 Y 是否派生自 enable_shared_from_this 选择的版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多