2015-05-09 88 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; 
}