2015-05-09 89 views
6

我有一个层次结构的操作和(共享)信息类,直观地看起来好像不需要运行时多态性,但是如果没有它,我无法找到解决方案。具有循环依赖性的CRTP

为了这个问题,假设有一个2级的层次结构。有一个基本操作和派生操作。来自同一级别的层次结构的对象可能需要在它们之间共享信息(这意味着基础操作对象需要共享基础信息,并且派生操作对象需要共享派生信息,但基础操作对象永远不需要共享派生信息或副作用反之亦然)。

所以它开始像这样:

// Shared between base operation objects 
class base_info 
{ 

}; 

// Shared between derived operation objects 
class derived_info : 
    public base_info 
{ 

}; 

由于没有运行时的问题,哪些操作对象共享哪些信息的对象,也有以下几点:

template<class Info> 
class base_op 
{ 
    std::shared_ptr<Info> m_info; 
}; 

class derived_op : 
    public base_op<derived_info> 
{ 

}; 

休息的代码总是使用base_information实例化base_op,因此不需要运行时多态性直到此处。

现在,在某些时候,共享信息对象可以决定他们需要产生新的操作。如上所见,操作对象需要共享指向共享信息对象的指针。因此,信息的层次结构变为:现在

// Shared between base operation objects 
class base_info : 
    private std::enable_shared_from_this<base_info> 
{ 
    void do_something_spawning_new_ops(); 
}; 

... 

的问题是如何实现do_something_spawning_new_ops。随着运行时间polymporphism,它并不难:

class base_info : 
    private std::enable_shared_from_this<base_info> 
{ 
    void do_something_spawning_new_ops() 
    { 
     // Need a new op. 
     get_op_shared_ptr(); 
    } 

    virtual std::shared_ptr<base_op> get_op_shared_ptr() 
    { 
     // use shared_from_this, create a base_op object using it. 
    } 
}; 

class derived_info : 
    public base_info 
{ 
    virtual std::shared_ptr<base_op> get_op_shared_ptr() 
    { 
     // use shared_from_this + std::*_pointer_cast, 
     // create a derived_op object 
    }  
}; 

,但关键是要避免运行时多态性,由于设计,一切都可以在实例是已知的。所以要回文章的开头,这本来是很高兴有这样的事情:

template<class Op> 
class base_info 
{ 

}; 

class derived_info : 
    public base_info<derived_op> 
{ 

}; 

与CRTP排序啄的(虽然没有推导),其中运说,它拥有的信息创建这种类型的对象。但是这现在导致base_op实例化的循环问题。它不知何故需要通过一些信息类型实例化,这些信息类型本身是通过它自己的类型实例化等等。我不知道如何制止这种类型循环。

编辑

继潘塔大黄的建议,here是我的目标代码。

+2

CRTP涉及从基地向下广播到派生。我在这里的任何地方都看不到。请提供说明问题的完整但最低限度的代码示例。 –

+0

循环依赖可以通过延迟模板实例化来解决。这可以通过添加另一个图层来完成。 – rpress

+0

你一直留下很多未知/模糊的东西在你的问题。请提供[MCVE](http://stackoverflow.com/help/mcve),或至少链接到一个例如使用像[Ideone](http://ideone.com/)这样的在线IDE。 –

回答

3

我还不是很确定你想要实现什么,但是你需要做的所有事情是让你的代码编译在base_info类模板中添加一个类型参数,当你在main中实例化时。

int main() 
{ 
    derived_op d; 
    base_op<base_info<derived_info> > b; 
}