Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 822
Armen Tsirunyan Avatar asked Sep 08 '11 17:09

Armen Tsirunyan


2 Answers

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.

like image 60
Begemoth Avatar answered Nov 09 '22 23:11

Begemoth


Something like this?

template <typename ...BaseClasses>
class Aggregator : public BaseClasses...
{
public:
    Aggregator(int i) : BaseClasses(i)...
    {}

};

Usage example:

Aggregator<U, V, W> a(10);
Aggregator<U, V> b(15);
Aggregator<W> c(20);

Note: it uses variadic templates, so C++11 is required.

like image 21
Matteo Italia Avatar answered Nov 10 '22 00:11

Matteo Italia