Reputation: 488
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.
Upvotes: 2
Views: 249
Reputation: 48447
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.
Upvotes: 3
Reputation: 2540
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();
}
Upvotes: 1