Typical characteristic for determining the primary base class

If I have a Base Base with at least one virtual function, and a Derived class that inherits separately from this, then (uintptr_t)derived - (uintptr_t)static_cast<Base*>(derived) guaranteed (by Itanium ABI) to be zero although Derived is not a standard layout. However, in the general case this is not necessarily true (for example, multiple inheritance).

Is it possible to write a trait that can be used to determine whether one class is the main base class of another?

Useful sections from Itanium ABI:

http://refspecs.linux-foundation.org/cxxabi-1.83.html

Main base class

For a dynamic class, a unique base class (if any) with which it shares a virtual pointer with an offset of 0. This is the first (in direct base class mode) non-virtual dynamic base class if one exists.

Dynamic class

A class that requires a virtual table pointer (because it or its bases have one or more virtual member functions or virtual base classes).

+7
source share
2 answers

This will be part of the next standard . This was part of an aborted TR2 using the std::bases and std::direct_bases . If you are working with a compiler that includes the TR2 project, you may 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; } 

Fingerprints:

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

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

I hope you can build a suitable "polymorphic and having exactly zero or one base".

+8
source

The following is a wild, not fully tested attempt to do something useful only with C ++ 11 (in fact, it does not actually require any C ++ 11 function, but itโ€™s easier to write this way).

However, this trait only verifies the transient closure of the โ€œprimary base classโ€ property: I could not understand the non-intrusive way of checking 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
source

All Articles