已知一批类型 A,B,C,D… 给定任意一个类型T, 如果T是这批类型中任意一个的子类,则返回其对应父类,否则返回T。
#include <iostream>
#include <type_traits>
class BaseA{};
class BaseB{};
class BaseC{};
class BaseD{};
template<class T, int8_t = (std::is_base_of<BaseA,T>::value)?1:
(std::is_base_of<BaseB,T>::value)?2:
(std::is_base_of<BaseC,T>::value)?4:
(std::is_base_of<BaseD,T>::value)?8:0>
struct IsDeriveFromBase{
typedef T type;
};
template<class T>
struct IsDeriveFromBase<T,1>{
typedef BaseA type;
};
template<class T>
struct IsDeriveFromBase<T,2>{
typedef BaseB type;
};
template<class T>
struct IsDeriveFromBase<T,4>{
typedef BaseC type;
};
template<class T>
struct IsDeriveFromBase<T,8>{
typedef BaseD type;
};
class DeriveA:public BaseA{};
class DeriveB:public BaseB{};
class DeriveC:public BaseC{};
class NoBase{};
int main(){
std::cout << typeid(IsDeriveFromBase<DeriveA>::type).name() << std::endl;
std::cout << typeid(IsDeriveFromBase<DeriveB>::type).name() << std::endl;
std::cout << typeid(IsDeriveFromBase<DeriveC>::type).name() << std::endl;
std::cout << typeid(IsDeriveFromBase<BaseA>::type).name() << std::endl;
std::cout << typeid(IsDeriveFromBase<NoBase>::type).name() << std::endl;
}
更好的做法是:
template <typename Base, typename Derived, bool = std::is_base_of_v<Base, Derived>>
struct ExtractBaseType {
static constexpr bool value = false;
typedef Derived type;
};
template <typename Base, typename Derived>
struct ExtractBaseType<Base, Derived, true> {
static constexpr bool value = true;
typedef Base type;
};
template <typename Derived, typename Base, typename... OtherBases>
struct ExtractBaseTypes
: public std::disjunction<ExtractBaseType<Base, Derived>, ExtractBaseType<OtherBases, Derived>...> {};
template <typename Derived, typename Base, typename... OtherBases>
using ExtractBaseTypes_t = typename ExtractBaseTypes<Derived, Base, OtherBases...>::type;