检测通用基类

假设有一个类层次结构,没有多重继承:

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

很明显,这不适用于多重舆论,但我关注单一继承案例。

首先,如果没有对基类进行一些反省,似乎是不可能的。 所以,我有这个更容易的问题,以这样一种方式来做,即每个Clase知道它的基础(通过内部base类型),例如:

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

即使这样,我似乎也无法获得元编程的权利。

我也读过某处(我现在无法找到它)GCC有一些扩展来检测通用基类。 是这样吗?


在std :: tr2中有一些基地和direct_bases ,但没有包括在内。 某些版本的gcc拥有它。 使用这些也许你可以得到你想要的。


如果你有每个类别的基地作为base (如下),它可以完成。

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

我创建了一个struct

template <class T1, class T2>
struct CommonBase;

CommonBase通过将T2每个基数与T1进行比较来工作。 当它到达顶层基地时,它再次从底部开始,但是与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;
};

在这里你可以在一些测试案例中看到它。

链接地址: http://www.djcxy.com/p/96219.html

上一篇: Detect common base class

下一篇: How to set application context path in angular2 routing properly?