Type trait to identify primary base class

前端 未结 2 2014
迷失自我
迷失自我 2021-01-12 07:02

If I have a class Base, with at least one virtual function, and a class Derived which inherits singly from this then (uintptr_t)derived - (uintptr_t)static_cast

相关标签:
2条回答
  • 2021-01-12 07:36

    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!");
    }
    
    0 讨论(0)
  • 2021-01-12 07:43

    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.

    0 讨论(0)
提交回复
热议问题