3

假设我有两个课程:ThingHolder

struct Thing :
        std::enable_shared_from_this<Thing>
{
    std::shared_ptr<Thing> self()
    {
        return shared_from_this();
    }
};

struct Holder :
        std::enable_shared_from_this<Holder>
{
    Thing t;
};

int main()
{
    auto h = std::make_shared<Holder>();
    // will throw std::bad_weak_ptr
    h->t.self();
}

我希望Thing's internalweak_ptr使用共享计数Holder,而不是要求 Holder保持 a shared_ptrto Thing。在相反的方向上,Thing需要能够在不知道 aHolder是什么的情况下存在(std::make_shared<Thing>().self()应该仍然有效)。有没有一种体面的方法来完成我正在寻找的东西?


不起作用的事情

说类似的东西是std::shared_ptr<Thing> t(h, &h->t);行不通的,因为 a 的别名构造函数std::shared_ptr不使用enable_shared_from_this访问者。

使用 Boost,可以通过重载来解决这个问题sp_enable_shared_from_this;然而,对于 g++ 的实现,如何做同样的事情并不明显__enable_shared_from_this_helper(更不用说我们正在跳入“不要那样做”的土地)。


提升解决方法

在 Boost 中,通过直接调用来解决这个问题并不难_internal_accept_owner

int main()
{
    auto h = boost::make_shared<Holder>();
    h->t._internal_accept_owner(&h, &h->t);
    h->t.self();
}

使用boost::enable_shared_from_this2,可以将所需的代码嵌入到构造函数中,Holder如下所示:

Holder()
{
    boost::shared_ptr<Holder> self = shared_from_this();
    t._internal_accept_owner(&self, &t);
}

我正在寻找与std::enable_shared_from_this.

4

2 回答 2

2

好的,现在我明白你在问什么,这是一个替代方案。您可以传入一个shared_ptr< Holder >to Thing,允许它创建自己的别名 shared_ptr。像这样的东西:

struct Thing : std::enable_shared_from_this<Holder>
{
     Thing() {};

     Thing( std::shared_ptr< Holder >& holderPtr ) :
     m_holder( holderPtr )
     {
     }

     std::shared_ptr< Holder > m_holder;


     std::shared_ptr<Thing> self()
     {
         try 
         { 
              return shared_from_this(); 
         }
         catch( const std::bad_weak_ptr& )
         {
              return std::shared_ptr< Thing >( m_holder, this );    
         }
     }
};

struct Holder : std::enable_shared_from_this<Holder>
{
    Thing t;
};

个人认为最好只保留一个shared_ptr< Thing >inside Holder,但如果你喜欢它,这似乎会起作用。除了 和 之间的循环Holder引用Thing。猜猜你可以用一个weak_ptr< Holder >内部Thing来代替。

于 2012-11-27T18:44:57.900 回答
1

如果您不介意,则可以通过私有继承而不是使用成员对象对 aThing内部的组合进行建模。Holder然后在你的一个成员中,你可以通过向下转换Thing“检索”封闭- 然后使用它来访问共享计数。Holderstatic_cast<Holder&>(*this)shared_from_this

但是,因为它是 的私有基础Holder,所以Thing需要一个朋友声明才能进行向下转换。由于除此之外,两个类之间的依赖关系是循环的,这导致了一些严重的耦合。

于 2012-11-27T19:47:41.500 回答