#include <algorithm>
#include <cassert>
#include <memory>
#include <vector>
struct Getter {
virtual int get() const = 0;
};
struct Changer {
virtual void change(int v) = 0;
};
struct DataStorage;
typedef std::vector<std::unique_ptr<DataStorage> > MList;
struct Registrar {
Registrar(MList &mlist) : mlist(mlist) { }
void add(std::unique_ptr<DataStorage>);
private:
MList &mlist;
};
void Registrar::add(std::unique_ptr<DataStorage> item)
{
mlist.push_back(std::move(item));
}
// Plugins can create new instances of this class as needed
struct DataStorage : Getter, Changer {
public:
DataStorage(int v)
: val(v)
{
}
virtual int get() const { return val; }
virtual void change(int v) { val = v; }
protected:
int val;
};
// List of data storage objects templated on which interface
// we want.
template <typename Base>
struct DataStorageList {
struct ItemAccessor {
ItemAccessor(MList &mlist)
: iter(mlist.begin()), end(mlist.end())
{
}
// Returns a null pointer if there are no more items
Base *nextPtr()
{
if (iter==end) return 0;
return (*iter++).get();
}
private:
MList::iterator iter, end;
};
DataStorageList(MList &mlist) : mlist(mlist) { }
ItemAccessor itemAccessor() const
{
return ItemAccessor(mlist);
}
private:
MList &mlist;
};
struct Plugin {
void initialize(Registrar ®istrar)
{
// Use registrar to register new data storage objects if needed
registrar.add(std::unique_ptr<DataStorage>(new DataStorage(1)));
}
void run(DataStorageList<Getter> getter_list)
{
// Use getter_list if you need access to the data storage objects
// but only as getters.
DataStorageList<Getter>::ItemAccessor
item_accessor = getter_list.itemAccessor();
while (Getter *getter_ptr = item_accessor.nextPtr()) {
// Do something with the getter_ptr
}
}
};
int main(int,char**)
{
MList mlist;
Registrar registrar(mlist);
Plugin plugin;
plugin.initialize(registrar);
DataStorageList<Getter> getter_list(mlist);
plugin.run(getter_list);
}