Search code examples
c++templatesboostmetaprogrammingboost-mpl

How to inherit from a list of types and then call a member on the list of inherited members?


I have a set of classes that have the following structure:

class U
{
public:
    explicit U(int) { ... }
    U() {...}
    Init(int) {...}
};

I need to be able to compose 1 or more of these classes into a class X. Pseudocode:

template<class TypeSequence>
class X that derives publicly from all the classes in TypeSequence
{
    X(int): all bases are initialized with the integer passed 
    {}
    //if the above constructor is impossible, then the following will do as well:
    X(int)
    {
        Call Init on all bases and pass the given int to them.
    }
};

I think I need a lot of mpl, but I'm not really good at it. Is what am I trying to do doable? A code sample would be great.

MY FAULT: Forgot to mention I can't use C++11 features. I am looking for an MPL solution.


Solution

  • Well, Boost.MPL contains metafunctions inherit and inherit_linearly you can combine them with for_each to get the second variant (with init functions). Or using just boost::mpl::fold and custom metafunctions:

    struct Null_IntConstructor
    {
      Null_IntConstructor(int) { }
    };
    
    struct InheritFrom_IntConstructor_Folder
    {
      template<typename T1, typename T2>
      struct apply
      {
        struct type : T1, T2
        {
          type(int x) : T1(x), T2(x) { }
        };
      };
    };
    
    template<typename Bases>
    struct InheritFrom_IntConstructor 
      : boost::mpl::fold<Bases, 
                         Null_IntConstructor,
                         InheritFrom_IntConstructor_Folder>::type
    {
      InheritFrom_IntConstructor(int x) 
        : boost::mpl::fold<Bases, 
                           Null_IntConstructor,
                           InheritFrom_IntConstructor_Folder>::type(x) 
      { }
    };
    

    Usage example:

    #include <iostream>
    #include <boost/mpl/fold.hpp>
    #include <boost/mpl/vector.hpp>
    
    struct A
    {
      A(int x) { std::cout << "A::A " << x << std::endl; }
    };
    
    struct B
    {
      B(int x) { std::cout << "B::B " << x << std::endl; }
    };
    
    struct C
    {
      C(int x) { std::cout << "C::C " << x << std::endl; }
    };
    
    int main()
    {
      InheritFrom_IntConstructor< boost::mpl::vector<A, B, C> >(1);
    }
    

    Metafunction InheritFrom_IntConstructor can generalized to accept arbitrary type as constructor parameter and I'm not sure if can generalized to accept arbitrary number of arguments.