检测共同碱基 class
Detect common base class
假设有一个 class 层次结构,没有多重继承:
struct TOP{};
struct L : TOP{};
struct R : TOP{};
struct LL : L{};
struct LR : L{};
struct RL : R{};
struct RR : R{};
是否可以编写一个元函数来 return 两种类型的公共基类型? (如果不存在公共基础 class,它可能 return 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
显然这不适用于多重继承,但我专注于单一继承的情况。
首先,如果不对基础进行一些反思,这似乎是不可能的 class。所以,我有一个更简单的问题,以这样一种方式来做到这一点,即每个类都知道它的基础(通过内部 base
类型),例如:
struct LR : L{using base = L;};
即使这样,我似乎也无法正确进行元编程。
我还在某处读到(我现在找不到)说 GCC 有一些扩展来检测公共基础 class。是这样吗?
在某个时候 bases and direct_bases
in std::tr2 but that wasn't included。某些版本的 gcc 有它。使用这些也许你可以得到你想要的。
如果每个 class 都将基数别名为 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;
};
Here你可以在一些测试用例上看到它。
假设有一个 class 层次结构,没有多重继承:
struct TOP{};
struct L : TOP{};
struct R : TOP{};
struct LL : L{};
struct LR : L{};
struct RL : R{};
struct RR : R{};
是否可以编写一个元函数来 return 两种类型的公共基类型? (如果不存在公共基础 class,它可能 return 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
显然这不适用于多重继承,但我专注于单一继承的情况。
首先,如果不对基础进行一些反思,这似乎是不可能的 class。所以,我有一个更简单的问题,以这样一种方式来做到这一点,即每个类都知道它的基础(通过内部 base
类型),例如:
struct LR : L{using base = L;};
即使这样,我似乎也无法正确进行元编程。
我还在某处读到(我现在找不到)说 GCC 有一些扩展来检测公共基础 class。是这样吗?
在某个时候 bases and direct_bases
in std::tr2 but that wasn't included。某些版本的 gcc 有它。使用这些也许你可以得到你想要的。
如果每个 class 都将基数别名为 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;
};
Here你可以在一些测试用例上看到它。