繁体   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