检测公共基类

问题描述:

假设一个具有类层次,没有多重继承:检测公共基类

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

在某些时候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> 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

如果您将每个班级别名设置为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你可以看到它的一些测试用例。