I’m using variadic templates with multiple virtual inheritance in C++ to aggregate types into a single structure definition.
Here is a sample set of structures:
struct meas { int i; };
struct meas2 : public virtual meas { int j; };
struct meas3 : public virtual meas { int k; };
I then aggregate these using multiple virtual inheritance:
template <typename... Args>
struct zipper : public virtual Args... {};
I can then do:
typedef zipper<meas, meas2> meas_type;
meas* m = new meas_type;
These can then cascade:
typedef zipper<meas3, meas_type> meas_type2;
The resulting object, however, is rather unwieldy:
$46 = (zipper<meas3, zipper<meas, meas2> >) {
<meas3> = {
<meas> = {
i = 0
},
members of meas3:
_vptr.meas3 = 0x400ec8,
k = 0
},
<zipper<meas, meas2>> = {
<meas2> = {
members of meas2:
_vptr.meas2 = 0x400ee0,
j = 6299120
},
members of zipper<meas, meas2>:
_vptr.zipper = 0x400eb0
}, <No data fields>}
according to gdb.
There is also a secondary problem when attempting to zip the same base type:
typedef zipper<meas, meas> meas_type2;
The above produces the compiler error “duplicate base class ‘meas’ is invalid” under G++ 4.6.3.
The question is thus twofold:
- Is there a way to transform
zipper<meas3, zipper<meas, meas2>>intozipper<meas3, meas2>? - Is there a way, while accomplishing #1, to remove duplicate entries in the type list?
Thanks!
My strategy for solving this problem is to use a few levels of indirection.
Example:
template < typename... Args > struct typelist {}to keep track of the object types from which you want to inherit.struct zipper < typelist < Args... > >: public virtual Args...to do the actual inheritanceIn order to get rid of duplicate parent types, two helper functions are used in
process_zipper_arguments:is_in < CandidateType, typelist< Args... > >::typeis eithertrue_typeorfalse_typeand can be defined recursivelyadd_unique < CandidateType, typelist< Args... > >::typeis atypelist <...>that has either CandidateType added to it or not. It callsis_into determine that.Here is the complete code that compiles at least with g++ (GCC) 4.6.3 with –std=c++0x. Criticism on it is welcome.
Debugging it gives the following result (breakpoint at the
return 0;line):