2

I realize that what I am trying to do is possibly wrong, so I would gladly accept and alternative approach. All code below is just an illustration.

Suppose I have a derived class, with multiple base classes:

template<typename... Bases> class Derived : public Bases...{
public:
    VariadicTemplate(BaseClasses&&... base_classes) : BaseClasses(base_classes)... {}

    void DoAllFoo();
};

And all the base classes have a method, named DoFoo(). I was going to derive them from a common base with a public method Foo():

class CommonBase {
public:
    virtual Foo() { DoFoo() };
protected:
    virtual void DoFoo() = 0;
};

class Base1 : public CommonBase {
    DoFoo() { /* displays something */ };
};

class Base2 : public CommonBase {
    DoFoo() { /* displays something else */ };
};

....

Now this is how I was going to use it. I want to instantiate some amount the Derived class objects, specified with different Base classes:

Devired<Base1, Base2> x;
Devired<Base5, Base7, Base21> y;
...
x.DoAllFoo();
y.DoAllFoo();

I want (somehow) the Derived's DoAllFoo() to "iterate" over it's Base classes and call each classes Foo() method.

The only solution I can imagine is to have some set of function pointers/functors/whatever in Derived and make all Bases register their Foo() method in this set when constructing. This will probably work, but look like it could be done better.

I hope, that I am not familiar with some common pattern to solve this problem (or I am just pure wrong), so please advise. Thank you.

Scott Tiger
  • 478
  • 2
  • 12

2 Answers2

3

You want either:

void DoAllFoo()
{
    using expand = int[];
    static_cast<void>(expand{ 0, (static_cast<Bases*>(this)->Foo(), void(), 0)... });
}

or:

void DoAllFoo()
{
    using expand = int[];
    static_cast<void>(expand{ 0, (Bases::Foo(), void(), 0)... });
}

depending on whether the call to Foo itself should be virtual or not.

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
1

The pattern I would use is simply composition as opposed to inheritance. Why don't you just make objects of base classes as members of what you now call Derived? You can simply store them into a std::vector and then iterate over it inside DoAllFoo.

For example:

class FooWrapper {

// ...

public:
  void DoAllFoos();

private:
  std::vector<std::unique_ptr<CommonBase> > bases_;   


} 

void FooWrapper::DoAllFoos() 
{
   for(auto& base: bases)
     base->DoFoo();
}
Emerald Weapon
  • 2,392
  • 18
  • 29
  • Well, I agree that that does makes scene, but I'm not sure if this solution's usage would be as flexible as the templated one. – Scott Tiger Mar 19 '16 at 11:55
  • I don't see any real need for templates here, unless I am missing something. – Emerald Weapon Mar 19 '16 at 11:57
  • could you please provide an example usage for your solution? – Scott Tiger Mar 19 '16 at 12:12
  • The usage would be identical to the one you are suggesting, with object instantiation instead of template instantiation (depending on the constructor that you choose to implement). For example a natural choice in this case could be to implement a constructor that takes an initializer list of base classes and uses it to initialize the internal vector. Instead of `Derived x;` you would have `FooWrapper x{Base1(), Base2()}`. – Emerald Weapon Mar 19 '16 at 13:27
  • Just to further clarify. My answer was based on the fact that you asked for an alternative approach. In my opinion the variadic template approach is a bit of an overkill for the problem. – Emerald Weapon Mar 19 '16 at 13:31
  • I see, thank you. I'm sorry for a misleading question, now I understand your suggestion perfectly. – Scott Tiger Mar 20 '16 at 18:42