2011-11-03 59 views
9

我有一個問題,我需要發現兩種類型(具有一個或零基類)的共同祖先,如果它存在。是否有可能建立一個類型特徵來解決這個問題?在代碼:如何在編譯時推斷兩種類型共有的繼承樹的根(如果存在)?

template<typename T1, typename T2> 
    struct closest_common_ancestor 
{ 
    typedef XXX type; // what goes here? 
}; 

考慮以下幾種類型:

struct root {}; 
struct child1 : root {}; 
struct child2 : root {}; 
struct child3 : child2 {}; 
struct unrelated {}; 

closest_common_ancestor會導致以下幾種類型:

closest_common_ancestor<root, child1>::type == root 
closest_common_ancestor<child1, child2>::type == root 
closest_common_ancestor<child3, child1>::type == root 
closest_common_ancestor<child3, child2>::type == child2 
closest_common_ancestor<unrelated, child1>::type == error 

我相信我能解決這個問題,如果我可以檢查是否類型具有零個或一個基類,如果是,則爲該類型的名稱。這可能嗎?

+2

您無法檢查基類。除非您手動爲每個類添加元信息。 –

+0

請注意,對於直接關係,已經有可能了('is_base_of'可以用基本的C++ 03塊來實現) –

+0

如果有2個根root1和root2,child1繼承child2 ('struct child1:root1,root2 {};'),那麼'nearest_common_ancestor'將會返回什麼。 – kennytm

回答

7

正如K-Ballo提到的,很不幸的是無法獲得一個班級所擁有的基地名單(太糟糕了......)。

如果您手動註釋類(例如,定義一個簡單的std::tuple<>列出的基地),那麼你可以使用這些信息。越簡單,當然是使用一個特點:

template <typename> struct list_bases { typedef std::tuple<> type; }; 

然後你就可以專注這個特質爲你的類型:

template <> struct list_bases<child1> { typedef std::tuple<root> type; }; 

從那裏開始,你就可以開始實驗,找到一個祖先......但它可能不是直接的。除了實現細節(遞歸獲取基礎,實現「距離」選擇)之外,我還期望出現「奇怪」情況的問題。

的距離選擇可以在通常的(線性)的繼承層次結構通過使用is_base_ofis_same的組合來解決,然而考慮以下層次結構:現在

struct root1 {}; struct root2 {}; 

struct child1: root1 {}; struct child2: root2 {}; 

struct child12: root1, child2 {}; struct child21: root2, child1 {}; 

child12child21有兩個共同的祖先: root1root2 ...哪個最接近?

它們是等價的。想想看,我補充一下:

struct root3 {}; struct child31: root3, child1 {}; 

然後root1是一個共同的祖先,以child12child21child31

但是如果我避開上的closest_common_ancestor定義和任意定義closest_common_ancesotr<child12, child21>root2,那麼我無法child31找到任何共同的祖先。

因此,我的建議是列出所有最接近的祖先,並使用tuple來實現設定操作。

+0

謝謝。對於我的應用程序,我會通過堅持所有考慮的類型只有零個或一個基本類型來解決您提到的模糊問題。 –