2017-05-06 65 views
7

假設一個具有類層次,沒有多重繼承:檢測公共基類

struct TOP{}; 
struct L : TOP{}; 
struct R : TOP{}; 
struct LL : L{}; 
struct LR : L{}; 
struct RL : R{}; 
struct RR : R{}; 

是否可以寫一元函數,它會返回兩種類型的共同基礎的類型? (如果沒有公共基類存在,它可能會返回void。) 例如

common_base<RR, R>::type == R 
common_base<RL, RR>::type == R 
common_base<LL, RR>::type == TOP 
common_base<LL, std::string>::type == void 

很明顯,這不會與多個inhertance工作,但我是集中在單繼承情況。

首先,如果沒有對基類進行一些反省,似乎並不可能。所以,我有這個簡單的問題,這樣做在這樣一種方式,每個CLASE知道它的底座(通過內部base型),例如:

struct LR : L{using base = L;}; 

即使這樣,我似乎無法得到的元編程對。

此外,我讀了某處(我現在無法找到它)GCC有一些擴展來檢測公共基類。是這樣嗎?

+0

'common_base :: type'是'RR'還是'R'? –

+0

@JamesRoot,'RR'。 – alfC

回答

3

在某些時候basesdirect_bases在std :: tr2 but that wasn't included。某些版本的gcc擁有它。使用這些也許你可以得到你想要的。

+0

感謝您的指針。我使用'#include '(...'6.3.1/tr2/type_traits:90:45:致命錯誤:'_Tp'不引用一個值 typedef __reflection_typelist <__ bases (_Tp)...> type;') – alfC

+0

GCC鏈接:https://gcc.gnu.org/onlinedocs/gcc-4.7.2/libstdc++/api/a00909.html – alfC

+0

@alfC您可能會有更好的運氣如果你降級到gcc 4.8.0或類似的東西。 – Pavel

1

如果您將每個班級別名設置爲base(如下所示),則可以完成。由T2每個基地比較T1

template <class T1, class T2> 
struct CommonBase; 

CommonBase作品:

struct Child : Parent { using base = Parent; }; //typedef works too 

我創建了一個struct。當它到達頂級基地時,它會再次從底部開始,但是與T1的基數進行比較。

例如:CommonBase<RL, RR>會經過以下檢查:

RL != RR 
RL != R 
RL != Top 
R != RR 
R == R 

所以CommonBase<RL, RR>::type == R。如果沒有共同基地,type == void

我把代碼在最後,因爲模板元編程是如此可愛:

#include <type_traits> 

template <class T> 
struct GetBase //type = T::base, or else void 
{ 
    template <class TT> static typename TT::base& f(int); 
    template <class TT> static void f(...); 
    typedef std::remove_reference_t<decltype(f<T>(0))> type; 
}; 

template <class T1, class T2> 
struct Compare2 //Compares T1 to every base of T2 
{ 
    typedef typename GetBase<T2>::type _type; 
    template <class T, bool = !std::is_same<T, void>::value> 
    struct helper 
    { 
     typedef typename Compare2<T1, T>::type type; 
    }; 
    template <class T> 
    struct helper<T, false> 
    { 
     typedef void type; 
    }; 
    typedef typename helper<_type>::type type; 
}; 

template <class T> 
struct Compare2<T, T> 
{ 
    typedef T type; 
}; 

template <class T1, class T2> 
struct Compare1 //Uses Compare2 against every base of T1 
{ 
    typedef typename GetBase<T1>::type _type; 
    template <class T, bool = !std::is_same<T, void>::value> 
    struct helper 
    { 
     typedef typename Compare1<T, T2>::type type; 
    }; 
    template <class T> 
    struct helper<T, false> 
    { 
     typedef void type; 
    }; 
    typedef std::conditional_t<std::is_same<typename Compare2<T1, T2>::type, void>::value, typename helper<_type>::type, typename Compare2<T1, T2>::type> type; 
}; 

template <class T> 
struct Compare1<T, T> //Probably redundant 
{ 
    typedef T type; 
}; 

template <class T1, class T2> 
struct CommonBase //You can throw a std::enable_if on this to limit it to class types 
{ 
    typedef typename Compare1<T1, T2>::type type; 
}; 

Here你可以看到它的一些測試用例。