[英]C++ check inheritance at compile time
我有一个基地 class
template<typename T>
class Base {};
和一些派生类:
class DerivedInt : public Base<int> {}
class DerivedDummy : public Base<Dummy> {}
// where Dummy is some user-defined concrete type
template<typename E>
class DerivedGeneric : public Base<E> {}
我希望编写一个类型特征 function f<DerivedType>::value
,它仅在存在类型T
时返回 true ,使得DerivedType
继承自Base<T>
。
我觉得 SFINAE 是通向 go 的路……但我对元编程黑魔法不太熟悉。 谢谢!
我相信C ++ 11中的类型支持模板是你想要的,特别是std :: is_base_of 。
我不确定,如果std::is_base_of
在这种情况下可能有用,但你肯定可以使用std :: is_convertible 。
如果存在类型T
,使得Derived
继承自Base<T>
,则意味着Derived
可以隐式转换为Base<T>
。
因此,您可以简单地使用以下解决方案。 它是以这种方式进行编译时检测,如果你调用类型的检查函数,它就不会编译,这不符合你的要求。 检查此代码:
#include <iostream>
struct Dummy
{
};
template<typename T>
class Base
{
};
class DerivedInt : public Base<int>
{
};
class DerivedDummy : public Base<Dummy>
{
};
template<typename E>
class DerivedGeneric : public Base<E>
{
};
template <class T>
bool is_derived_from_base_t_impl(Base<T>* impl)
{
return true;
}
template <class Derived>
bool is_derived_from_base_t()
{
Derived* d = nullptr;
return is_derived_from_base_t_impl(d);
}
int main()
{
std::cout<< is_derived_from_base_t< DerivedInt >() <<"\n";
std::cout<< is_derived_from_base_t< DerivedDummy >() <<"\n";
std::cout<< is_derived_from_base_t< DerivedGeneric<float> >() <<"\n";
return 0;
}
输出:
1
1
1
但是,如果你这样做:
is_derived_from_base_t< float >();
你会得到:
error C2784: 'bool is_derived_from_base_t_impl(Base<T> *)' : could not deduce template argument for 'Base<T> *' from 'float *'
(VC ++ 11的输出)
改进Mateusz Grzejek的解决方案,使其成为真正的特质:
template <class T>
std::true_type is_derived_from_base_t_impl(const Base<T>* impl);
std::false_type is_derived_from_base_t_impl(...);
template <class Derived>
using is_derived_from_base_t =
decltype(is_derived_from_base_t_impl(std::declval<Derived*>()));
请注意,不处理多重继承。
又回答了几个方面
* 独立于 C++11 功能
* 私人 inheritance
* 虚拟 inheritance
* 多个 inheritance
* inheritance 来自结构
* 对称关系,即正向或反向inheritance
/**
* Class Template InheritanceCheck
* @param Candidate - type optionally inherited from Base
* @param Base - base class/struct
*/
template<typename Candidate, typename Base>
class InheritanceCheck
{
static char Test(Base*);
static int Test(...);
static void Constraints(Candidate* p) { }
InheritanceCheck()
{
void(*p)(Candidate*) = Constraints;
};
public:
/**
* isSub, true when Candidate is derived from Base
*/
static const bool isSub = sizeof(Test(static_cast<Candidate*>(0))) == sizeof(char);
/**
* isRelated, true when Candidate is derived from Base OR Base is derived from Candidate
*/
static const bool isRelated = isSub || InheritanceCheck<Base,Candidate>::isSub;
};
// Access policy for class InheritanceCheck in case of protected/private inheritance
#define ICP template<typename Candidate, typename Base> friend class InheritanceCheck
/* Example */
class A {};
class B : virtual A { ICP; };
class C : public virtual A, public B {};
struct D {};
struct S {};
class Z : public S {};
int main()
{
std::cout << "B->A " << InheritanceCheck<B, A>::isSub << std::endl;
std::cout << "C->A " << InheritanceCheck<C, A>::isSub << std::endl;
std::cout << "C->B " << InheritanceCheck<C, B>::isSub << std::endl;
std::cout << "D->A " << InheritanceCheck<D, A>::isSub << std::endl;
std::cout << "A->B " << InheritanceCheck<A, B>::isSub << std::endl;
std::cout << "A~B " << InheritanceCheck<A, B>::isRelated << std::endl;
std::cout << "S->A " << InheritanceCheck<S, A>::isSub << std::endl;
std::cout << "Z->S " << InheritanceCheck<Z, S>::isSub << std::endl;
}
Output:
B->A 1
C->A 1
C->B 1
D->A 0
A->B 0
A~B 1个
S->A 0
Z->S 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.