[英]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.