Type trait to identify primary base class

旧城冷巷雨未停 提交于 2019-12-01 04:13:20

This will be part of the next standard This was part of the aborted TR2 via the std::bases and std::direct_bases traits. If you happen to be working with a compiler that includes the draft-TR2, you might have support for this. For example in GCC 4.7.2:

#include <demangle.hpp>
#include <iostream>
#include <tr2/type_traits>

struct T1 { };
struct T2 { };
struct Foo : T1, T2 { };


int main()
{
    std::cout << demangle<std::tr2::direct_bases<Foo>::type>() << std::endl;
}

This prints:

std::tr2::__reflection_typelist<T1, T2>

(The demangler is my own; you may have seen it elsewhere.)

I trust you can build a suitable "is polymorphic and has precisely zero or one bases" trait yourself.

Below is a wild, not thoroughly tested attempt at doing something helpful with C++11 only (actually, it does not really require any C++11 feature, but it's easier to write this way).

However, this trait only checks the transitive closure of the "is primary base class of" property: I could not figure out a non-intrusive way of verifying whether a class is a direct base class of another class.

#include <type_traits>

template<typename B, typename D, D* p = nullptr, typename = void>
struct is_primary_base_of : std::false_type { };

template<typename B, typename D, D* p>
struct is_primary_base_of<B, D, p,
    typename std::enable_if<
        ((int)(p + 1024) - (int)static_cast<B*>(p + 1024)) == 0
        >::type
    >
    :
    std::true_type { };

Here is an example:

struct A { virtual ~A() { } };

struct B : A { };

struct C { virtual ~C() { } };

struct D : B, C { };

struct E : virtual A, C { };

int main()
{
    // Does not fire (A is PBC of B, which is PBC of D)
    static_assert(is_primary_base_of<A, D>::value, "Error!");

    // Does not fire (B is PBC of C)
    static_assert(is_primary_base_of<B, D>::value, "Error!");

    // Fires (C is not PBC of D)
    static_assert(is_primary_base_of<C, D>::value, "Error!");

    // Fires (A is inherited virtually by E, so it is not PBC of E)
    static_assert(is_primary_base_of<A, E>::value, "Error!");

    // Does not fire (C is the first non-virtual base class of E)
    static_assert(is_primary_base_of<C, E>::value, "Error!");
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!