Suppose I have the following classes:
class BaseObject {
public:
virtual int getSomeCommonProperty();
};
class Object1: public BaseObject {
public:
virtual int getSomeCommonProperty(); // optional
int getSomeSpecificProperty();
};
class BaseCollection {
public:
virtual void someCommonTask();
};
class Collection1: public BaseCollection {
public:
virtual void someCommonTask(); // optional
void someSpecificTask();
};
Each collection, derived from BaseCollection, deals with a specific object type (and only one type). But BaseCollection should be able to perform some tasks that are common to all objects, using only common object properties in BaseObject.
Currently, I have potentially three solutions in mind:
1) Store the objects list in BaseCollection, such as:
class BaseCollection {
vector<BaseObject*> objects;
};
The problem with this solution is that when I need to perform object-specific task in Collection1, I need a dynamic_cast<>, because I don't want to use virtual inherance for specific properties, applying to only one type of object. Considering that dynamic_cast<> could potentially get called millions of time per second, this seems an issue for a performance critical application.
2) Store the objects list in Collection1, such as:
class Collection1: public BaseCollection {
vector<Object1*> objects;
}
But then I need some way to access this object list in BaseCollection, to be able to perform some common tasks on them, ideally through an iterator. I would need to create a function that return a vector for the BaseCollection, but again, this does not seem very efficient, because the only way to do that is to create a new vector (potentially containing thousands of objects)...
3) Store the objects list in BaseCollection AND Collection1:
class BaseCollection {
public:
void someCommonTask(); // Use baseObjects
virtual void addObject() = 0;
protected:
vector<BaseObject*> baseObjects;
};
class Collection1: public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
}
Where the two lists actually contain the same objects. Is that as ugly as it sounds like?
I am looking for the right/correct/best design pattern for this type of problem and none of the 3 solutions exposed above really satisfies me...
Maybe it is possible to solve that problem with templates, but then I don't see a way to store a list of polymorphic collections like this:
vector<BaseCollection*> collections;
You can store all your objects of base and derived classes in one collection through the base class (smart) pointer. Using visitor design pattern and double dispatch mechanism you can call a function only on objects of a specific type without having to expose that function in the base class interface. For example:
#include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <stdio.h>
struct Visitor { // Visitor design patter
virtual void visit(struct BaseObject&) {}
virtual void visit(struct Object1&) {}
};
struct BaseObject {
unsigned ref_count_; // intrusive_ptr support
BaseObject() : ref_count_() {}
virtual ~BaseObject() {}
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
void intrusive_ptr_add_ref(BaseObject* p) { // intrusive_ptr support
++p->ref_count_;
}
void intrusive_ptr_release(BaseObject* p) { // intrusive_ptr support
if(!--p->ref_count_)
delete p;
}
struct Object1 : BaseObject {
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
void getSomeSpecificProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class T, class Functor>
struct FunctorVisitor : Visitor {
Functor f_;
FunctorVisitor(Functor f) : f_(f) {}
void visit(T& t) { f_(t); } // apply to T objects only
template<class P> void operator()(P const& p) { p->accept(*this); }
};
template<class T, class Functor>
FunctorVisitor<T, Functor> apply_to(Functor f)
{
return FunctorVisitor<T, Functor>(f);
}
int main()
{
typedef boost::intrusive_ptr<BaseObject> BaseObjectPtr;
typedef std::vector<BaseObjectPtr> Objects;
Objects objects;
objects.push_back(BaseObjectPtr(new BaseObject));
objects.push_back(BaseObjectPtr(new Object1));
for_each(
objects.begin()
, objects.end()
, boost::bind(&BaseObject::getSomeCommonProperty, _1)
);
for_each(
objects.begin()
, objects.end()
, apply_to<BaseObject>(boost::bind(&BaseObject::getSomeCommonProperty, _1))
);
for_each(
objects.begin()
, objects.end()
, apply_to<Object1>(boost::bind(&Object1::getSomeSpecificProperty, _1))
);
}
Output:
$ ./test
virtual void BaseObject::getSomeCommonProperty()
virtual void Object1::getSomeCommonProperty()
virtual void BaseObject::getSomeCommonProperty()
void Object1::getSomeSpecificProperty()
I think you should go for option 1 but use a static cast instead. After all the derived collection knows the type of the member variable for sure.
This answer explains it very well.
Id use nested adapter as in below example. You have to specialize it for every class you want to do a fancy update
!The example has memory leak - allocated A, B, Q objects are not deleted!
#include <iostream>
#include <vector>
#include <algorithm>
class Q
{
public:
virtual void Foo()
{
std::cout << "Q::Foo()" << std::endl;
}
};
class A
{
public:
virtual void Foo()
{
std::cout << "A::Foo()" << std::endl;
}
};
class B : public A
{
public:
virtual void Foo()
{
std::cout << "B::Foo()" << std::endl;
}
virtual void BFoo()
{
std::cout << "B::BFoo()" << std::endl;
}
};
template <typename ElementType>
class C
{
public:
template <typename T>
void add(T* ptr){m_Collection.push_back(std::unique_ptr<Adapter>(new ConcreteAdapter<T>(ptr)));}
void updateAll()
{
std::for_each(m_Collection.begin(), m_Collection.end(), [&](std::unique_ptr<Adapter> &adapter)->void{adapter->update();});
}
private:
class Adapter
{
public:
virtual ElementType* get() = 0;
virtual void update(){get()->Foo();}
};
template <typename T>
class ConcreteAdapter : public Adapter
{
public:
ConcreteAdapter(T* ptr) : m_Ptr(ptr){}
virtual T* get(){return m_Ptr;}
protected:
T* m_Ptr;
};
template <>
class ConcreteAdapter<B> : public Adapter
{
public:
ConcreteAdapter(B* ptr) : m_Ptr(ptr){}
virtual B* get(){return m_Ptr;}
virtual void update()
{
get()->Foo();
get()->BFoo();
}
private:
B* m_Ptr;
};
std::vector<std::unique_ptr<Adapter>> m_Collection;
};
int main()
{
C<A> c;
c.add(new A());
c.add(new B());
//c.add(new Q()); //error - correct
c.updateAll();
return 0;
}
Maybe this will do the trick here ?
class CollectionManipulator {
public:
void someCommonTask(BaseCollection& coll) {
for(unsigned int i = 0; i < coll.size(); i++)
someCommonTask(coll.getObj(i));
}
private:
void someCommonTask(BaseObject*); // Use baseObjects
};
class BaseCollection {
friend class CollectionManipulator;
private:
virtual BaseObject* getObj(unsigned int) = 0;
virtual unsigned int size() const = 0;
};
class Collection1 : public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
private:
BaseObject* getObj(unsigned int value) {
return object[value];
}
unsigned int size() const {
return objects.size();
}
}
If you want abstract your container in Collection1 (like using list instead using vector), to use it in Manipulator, create an abstract iterator...
I think the solution should be a mix of factory method pattern and template method pattern. Take a look at those to refine your design.
Edit: Here is a sample code. GenericProduct is the BaseObject, it provides two methods, one that is general (though it could be overridden), and a specific method which does nothing, it is not a pure virtual so this class can be instantiated. SpecificProduct is a subclass, which implements the specific method in some way.
Now, Factory class is an abstract class that defines an interface for creating specific products by specific factories, it defines a pure virtual method createProduct which creates the product. Two concrete factories are created GenericFactory and SpecificFactory which create specific products.
Finally, the Consumer abstract class (which corresponds to BaseCollection in your code), it defines a pure virtual method for creating a factory createFactory in order to force subclasses to create their own concrete factories (and hence, the correct products). The class also define a method fillArray (prototype pattern) to fill the array with products created by the factory.
#include <iostream>
#include <vector>
using namespace std;
class GenericProduct{
public:
virtual void getSomeCommonProperty()
{
cout<<"Common Property\n";
}
virtual void getSomeSpecificProperty()
{
cout<<"Generic Has Nothing Specific\n";
}
};
class SpecificProduct : public GenericProduct{
public:
virtual void getSomeSpecificProperty()
{
cout<<"Specific Product Has a Specific Property\n";
}
};
class Factory
{
public:
virtual GenericProduct* createProduct() = 0;
};
class GenericFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new GenericProduct();
}
};
class SpecificFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new SpecificProduct();
}
};
class Consumer
{
protected:
vector<GenericProduct*> gp;
Factory* factory;
protected:
virtual void createFactory() = 0;
public:
void fillArray()
{
createFactory();
for(int i=0; i<10; i++)
{
gp.push_back(factory->createProduct());
}
}
virtual void someCommonTask()
{
cout<<"Performaing a Common Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeCommonProperty();
}
}
virtual void someSpecificTask()
{
cout<<"Performaing a Specific Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeSpecificProperty();
}
}
};
class GenericConsumer : public Consumer
{
virtual void createFactory()
{
factory = new GenericFactory();
}
};
class SpecificConsumer : public Consumer
{
virtual void createFactory()
{
factory = new SpecificFactory();
}
};
int main()
{
Consumer* c = new GenericConsumer();
c->fillArray();
c->someCommonTask();
return 0;
}
Related
i know there is nothing like virtual template method in C++, but as it seems it is exactly what i need. Is there any workaround i could use? I am thankful for any suggestion.
I would like to add Entities to a vector by a add method, which need to be virtual and also template, how to avoid this?
#include <iostream>
#include <vector>
class EntityBase {
public:
};
class EntityDerived1 : public EntityBase {
public:
};
class EntityDerived2 : public EntityBase {
public:
};
class ContainerBase {
public:
template<typename T>
virtual void add() = 0; // i know this is not allowed!!!
};
class ContainerConcrete : public ContainerBase {
public:
template<typename T>
void add() override { // i know this is not allowed!!!
data.push_back(std::make_shared<T>());
}
void doSecretStuffWithDataHere() {
// ...
}
private:
std::vector<std::shared_ptr<EntityBase>> data;
};
class Engine {
public:
Engine() :
container(std::make_shared<ContainerConcrete>())
{}
ContainerBase& getContainer() {
auto rawPointer = container.get();
return *container;
}
private:
std::shared_ptr<ContainerConcrete> container;
};
int main() {
Engine engine;
ContainerBase& container = engine.getContainer();
container.add<EntityDerived1>();
container.add<EntityDerived2>();
}
Just make add a regular virtual function that takes shared_ptr as a parameter
class ContainerBase {
public:
virtual void add(std::shared_ptr<EntityBase>) = 0;
};
class ContainerConcrete : public ContainerBase {
public:
void add(std::shared_ptr<EntityBase> p) override {
data.push_back(p);
}
// . . .
And then invoke it with make_shared for the desired type:
int main() {
Engine engine;
ContainerBase& container = engine.getContainer();
container.add(std::make_shared<EntityDerived1>());
container.add(std::make_shared<EntityDerived2>());
}
Alternatively you can add a templated overload that invokes make_shared:
virtual void add(std::shared_ptr<EntityBase>) = 0;
template<typename T>
void add() {
add(std::make_shared<T>());
}
I have a class MyClass (with several virtual functions) that performs operations on an object called MyType.
The class MyClassImpl inherits MyClass and implements the virtual functions, but I need to add additional members to MyType, but I don't want to modify the class MyType (instead I want to keep it generic).
Now, if I make a MyTypeImpl and inherit MyType, I can add members. But, how do I make the non virtual functions in MyClassImpl (inherited from MyClass) use the new MyTypeImpl?
The only way I can think is to make MyClass use MyTypeImpl but I want to avoid using the implementation in the generic class because I might use various different implementations.
Here is a simple example of what the classes might look like. Of course, the code will not compile because the methods and members added in MyTypeImpl and not MyType.
class MyType {
public:
void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
class MyTypeImpl : public MyType {
public:
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClassImpl : public MyClass{
public:
void print() {
mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_.increment();
mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_.decrement();
mytype_.decrement();
};
};
After seeing your example I see now that you just want to extend the functionality of that class without modifying the original class. If you need to add additional functions, but you don't want to change the type that is stored in MyClass there isn't any way I know of to make that happen without at least modifying MyType to include virtual functions for the functions you want to call.
You also need to make MyClass take a pointer to MyType so you can use polymorphism and make the calls resolve to the correct implementation:
Dynamic Polymorphism Solution:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
// To be implemented by implementation class
virtual void print() = 0;
// To be implemented by implementation class
virtual void decrement() = 0;
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << 42 << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClass {
public:
MyClass(MyType* mytype)
: mytype_(mytype)
{}
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType* mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_->increment();
};
};
class MyClassImpl : public MyClass{
public:
MyClassImpl(MyType* mytype)
: MyClass(mytype)
{}
void print() {
mytype_->print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_->increment();
mytype_->increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_->decrement();
mytype_->decrement();
};
};
int main()
{
MyType* mytype = new MyTypeImpl();
MyClass* myclass = new MyClassImpl(mytype);
// Prints "42"
myclass->print();
// Do other stuff with "myclass"
delete myclass;
delete mytype;
}
Note, I am only using a raw pointer in this example for increased clarity. It is highly recommended that you don't use new and delete and use smart pointers to manage the lifetime of your pointers instead.
Static Polymorphism Solution:
Not that the design of this solution is actually any better, but I think this is closer to what you are actually looking for because it doesn't require modifying the MyType class directly. Also the only modification needed for MyClass is to make it a template class:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << data_ << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;
};
template <typename T>
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
T mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
template <typename T>
class MyClassImpl : public MyClass<T> {
public:
void print() {
this->mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
this->mytype_.increment();
this->mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
this->mytype_.decrement();
this->mytype_.decrement();
};
};
int main()
{
// Use the template to get the correct implementation
MyClassImpl<MyTypeImpl> myclass;
myclass.alg();
myclass.print();
// Do other stuff with my class
}
Let say I've this code with a EnvelopeMultiPoints class template:
#include <iostream>
#include <vector>
class EnvelopeMultiPointsBase
{
// base
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
void Process() {
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch> { };
template<typename T>
unsigned int EnvelopeMultiPoints<T>::mNumPoints = 5;
class Container
{
public:
EnvelopeMultiPointsBase *pAssociatedEnvelope;
Container(EnvelopeMultiPointsBase *associatedEnvelope) : pAssociatedEnvelope(associatedEnvelope) { }
~Container() { }
void Process();
private:
};
int main()
{
EnvelopeMultiPoints<Pitch> pitch;
Container container(&pitch);
container.pAssociatedEnvelope->Process();
}
And I want to pass to the Container any kind of "EnvelopeMultiPoints" types (a generic "pointer"), so later I can access to its own method (in my case, Process()).
Does it means that also Container must be templated? (which is huge in my real scenario; lot of works to transform all of its methods in template, translate header/cpp, and such).
Or is there a trick that I'm missing?
In few words: let say that I want to pass to Container EnvelopeMultiPoints<Pitch>, and than execute Process(). Later, I want to pass EnvelopeMultiPoints<Volume> instead, and than execute Process(). And so on. Is there a way to do this without converting also Container to a template?
The technique you need is called dynamic polymorphism
that is implemented in C++ by virtual functions.
Illustrating using your code:
class EnvelopeMultiPointsBase
{
public:
// Abstract base, no actual implementation
virtual void Process() = 0;
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
// Some specific implementation.
virtual void Process() override
{
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch>
{
};
To call the Process function of the base class, you have to define it in the base class. You can move the implementation to templated child classes:
class EnvelopeMultiPointsBase
{
private:
virtual void ProcessImpl() = 0;
public:
void Process() {
//potential common code...
ProcessImpl();
//more potential common code...
}
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
private:
void ProcessImpl() {
std::cout << "process" << std::endl;
}
};
My code structure is like below where multiple classes implement Interface. In Example class I store a pointer to the Interface and new() it in the constructor appropriately (depending on constructor parameters not shown here). I'm looking for ways to avoid using new() in this scenario but haven't got a solution yet. What's the best practice for something like this?
class Interface
{
virtual void Foo() = 0;
};
class A : public Interface
{
void Foo() { ... }
};
class B : public Interface
{
void Foo() { ... }
};
class Example
{
private:
Interface* m_bar;
public:
Example()
{
m_bar = new A(); // deleted in destructor
}
};
There are two ways this is typically done, each with their own merits.
If A is truely defined at compile time, than a typical way to handle this is to simply use a template type:
template <typename T>
class TemplateExample
{
T m_bar;
public:
TemplateExample() : m_bar() {};
}
This has some downsides. TemplateExample<A> becomes unrelated to TemplateExample<B>, the error messages when T doesn't follow the correct interface are pretty obtuse, ect. The upside is this may use duck typing rather than interface typing, and m_bar is a concrete instance.
The other (arguable more common) way is to do the following
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
};
This has the benefit of being able to be run time configuratble if you follow a cloable pattern:
class Interface
{
public:
virtual void Foo() = 0;
virtual Interface* clone() const = 0;
};
template <typename T>
class CloneHelper : public Interface
{
public:
virtual Interface* clone() const { return new T(static_cast<const T&>(*this));}
};
class A : public CloneHelper<A>
{
virtual void Foo() { std::cout << 'A' << std::endl; }
};
class B : public CloneHelper<B>
{
virtual void Foo() { std::cout << 'B' << std::endl; }
};
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
UniquePtrExample(const Interface& i) : m_bar(i.clone());
};
Note you can further extend the above to have a move variant of the clone function.
Imagine I have a class 'BaseA' that contains a collection of items 'ItemA'.
Now I want to extend 'BaseA' to add extra capabilities, so I derive 'DerivedA' from 'BaseA'.
One characteristic of 'DerivedA' is that it has to handle more sophisticated 'DerivedITemA' items instead of 'ItemA' ones.
class BaseA {
protected:
vector<ItemA> x;
void m1(int i) { x.m1(i); }
};
class ItemA {
protected:
void m1(int i) { ... }
};
class DerivedItemA : public ItemA {
void m2(int i) { ... }
};
Now I would like to handle something of this sort:
class DerivedA : public BaseA {
vector<DerivedItemA> x;
void m2(int i) { x[i].m2(); }
};
I.e. have my Derived class handle derived items. The above definition of x is incorrect as it clashes with the one in BaseA. But the idea is I want to be able to reuse all methods in BaseA that handle x as long as they deal with ItemA elements and have the extended methods in DerivedA to handle the extra intricacies of DerivedItemA type of data
Any suggestion? My current thoughts are in the lines of defining a new datatype for x (VectorOfItemA for instance) and derive from it VectorOfDerivedItemA. I wonder if there is a simpler / better solution.
Thanks
I believe you need to have pointers in your vectors in order to handle this. I'm a little confused what value to pass to m1 and m2 since i appears to be an index, but here's my guess:
class BaseA {
protected:
vector<ItemA*> x;
void m1(int i) { x[i]->m1(i); }
};
class ItemA {
protected:
void m1(int i) { ... }
};
class DerivedItemA : public ItemA {
void m2(int i) { ... }
};
class DerivedA : public BaseA {
vector<DerivedItemA*> y; //don't shadow the base class vector!
void m2(int i) { y[i]->m2(i); }
};
Then, when you add an item in DerivedA, add it to both x and y. That way BaseA can do it's thing to the pointer in x and DerivedA can do its thing on the pointer in y.
Edit: you'll also need to provide a virtual method for adding items otherwise you might get things added to BaseA.x that don't get added to DerivedA.y.
Do you own all the classes? If so, you can refactor into a template base class instead.
template <typename ITEM>
class BaseT {
protected:
vector<ITEM> x;
void m1(int i) { x[i].m1(); }
};
typedef BaseT<ItemA> BaseA;
class DerivedA: public BaseT<DerivedItemA> {
void m2(int i) { x[i].m2(); }
};
If you intend to re-use code that takes BaseA to also accept a DerivedA, then you may need to modify them to be template functions/classes as well.
Otherwise, you will need some kind of "polymorphic" base object for the vector. You can look at Retrieve data from heterogeneous std::list (or my follow up question: unique_ptr member, private copy constructor versus move constructor) for one such approach.
As an alternative to a polymorphic item, you can define an interface for your base.
class BaseI {
protected:
virtual void m1(int) = 0;
//... other interfaces
public:
virtual ~BaseI () {}
//... other public interfaces
};
template <typename ITEM>
class BaseT : public BaseI {
protected:
vector<ITEM> x;
void m1(int i) { x[i].m1(); }
//...implement the other interfaces
};
//...
Now, code that takes a BaseA needs to be refactored to take a BaseI instead. That new code will be able to accept a DerivedA as well.
You may try to use Curiously Recurring Template Pattern - CRTP:
live demo
#include <iostream>
#include <ostream>
#include <vector>
using namespace std;
struct Item
{
void m1(int i)
{
cout << "m1(" << i << ")" << endl;
}
};
struct DerivedItem : Item
{
void m2(int i)
{
cout << "m2(" << i << ")" << endl;
}
};
template<typename Derived>
struct IBase
{
void m1(int i)
{
for(auto &&z : static_cast<Derived*>(this)->x)
{
z.m1(i);
}
}
};
template<typename Derived>
struct IDerivedBase: IBase<Derived>
{
void m2(int i)
{
for(auto &&z : static_cast<Derived*>(this)->x)
{
z.m2(i);
}
}
};
struct Base : IBase<Base>
{
vector<Item> x;
};
struct DerivedBase : IDerivedBase<DerivedBase>
{
vector<DerivedItem> x;
};
int main()
{
Base b;
b.x.resize(3);
DerivedBase d;
d.x.resize(1);
b.m1(11);
d.m1(22);
d.m2(33);
}
Output is:
m1(11)
m1(11)
m1(11)
m1(22)
m2(33)
Vector will contain either all elements as ItamA in BaseA instantiations or all elements of DerivedItemA in DerivedA instantiaions. There is no need to mix.
There is no any mix at this approach:
Base has only vector<Item> providing m1 method
DerivedBase has only vector<DerivedItem> providing m1 and m2 methods.
However, without knowing real usage pattern - it is hard to guess what you need. Maybe for your case two standalone vectors would be enough:
vector<Item> x1;
vector<DerivedItem> x2;
and just define stand-alone functions for them.