2017-02-20 92 views
2

我有一個類層次結構:獲取最近的基地

struct B {}; 
struct D1 : B {}; 
struct D2 : B {}; 

使用某種std::輔助函數/類的(可能來自<type_traits>)獲得公共基類是否有可能(即B)兩個變量:

D1 d1; 
D2 d2; 

我曾嘗試使用std::common_type_t<decltype(d1), decltype(d2)>,但沒有運氣。

+3

鑑於'結構D1:B1,B2 {};'和'結構D2:B1,B2 {};',會發生什麼? – Quentin

+0

@Quentin不錯的問題:)我忘記了多重繼承 – alexolut

+0

@Quentin在多重繼承的情況下,任何'B1','B2'都可以適合我。 – alexolut

回答

2

http://www.cplusplus.com/reference/type_traits/common_type/

如果你看看實現common_type代碼,看來,它被輸入到列表中的類型之間進行選擇。這是參考的行爲:

template <class... Types> struct common_type; 

template <class T> struct common_type<T> { 
    typedef T type; 
}; 

template <class T, class U> struct common_type<T,U> { 
    typedef decltype(true?declval<T>():declval<U>()) type; 
}; 

template <class T, class U, class... V> struct common_type<T,U,V...> { 
    typedef typename common_type<typename common_type<T,U>::type,V...>::type  type; 
}; 

所以,如果你只輸入一個「T」型,則返回該類型的一個typedef。如果你輸入兩種類型,「魔術師」在此行中發生:(?X Y:Z)

true?declval<T>():declval<U>() 

它採用了三元指示這樣做是有一個始終保持真實參數兩種可能的結果之間挑。由於三元組只能有一種返回類型,因此C++的普通轉換規則適用:應用標準轉換規則以確保該指令只有一種返回類型。這是這裏的「訣竅」。當你插入一個D1和一個D2時,這個過程會失敗,因爲三元指令不知道要把D1和D2都變成什麼。所以common_type依賴於C++中已經存在的轉換邏輯,並且實際上找不到類「B」。

事實上,您可以同時檢查B對D1或B對D2或B/D1/D2(它使用模板遞歸來解決三個或更多),並且這些common_type調用中的每一個都會正確地分辨你認爲B是常用的類型,但是在檢查中不包括B,代碼實現不能爲你返回B.

如果你想要你想要的東西,你可能需要專門爲你所追求的課程級別構建它。

+0

很好的答案。看起來病態的人不得不在我當前的模板中手動傳遞「共享」基本類型。 –