簡體   English   中英

C++ 在編譯時檢查 inheritance

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM