I want to store an arbitrary number of different classes (all shared-pointered) in some manager-class. The different classes have to be derived from the same CRTP-interface-class. Finally, I want to be able to iterate over all stored classes and calling some functions of the interface. I do not want to create a common base class and I want only use compile-timed stuff.
So I read a few articles in the internet and stole some concepts together. Now I have a working solution (I hope, I am new to templates in C++!), but I think, that is by far too much overkill for such a "simple" requirement.
Can you plz help me to optimize (simplify/shrink/modify) the following minimal example or provide some smarter solution? (no boost and only C++11/14/17)
#include <iostream>
#include <tuple>
#include <memory>
template <class T_IMPLEMENTATION>
struct ISystem {
bool run(int i) { return static_cast<T_IMPLEMENTATION*>(this)->runImpl(i); }
};
struct SystemA : public ISystem<SystemA> {
friend ISystem<SystemA>;
private:
bool runImpl(int i) { std::cout << this << " A:" << i << std::endl; return i; };
};
struct SystemB : public ISystem<SystemB> {
friend ISystem<SystemB>;
private:
bool runImpl(int i) { std::cout << this << " B:" << i << std::endl; return i; };
};
template<typename... ARGS>
struct SystemManager {
template <int index, typename... Ts>
struct runSystem {
void operator()(std::tuple<Ts...>& t, int i) {
std::get<TUPLE_SIZE - index - 1>(t)->run(i++);
runSystem<index - 1, Ts...>{}(t, i);
}
};
template <typename... Ts>
struct runSystem<0, Ts...> {
void operator()(std::tuple<Ts...>& t, int i) {
std::get<TUPLE_SIZE - 1>(t)->run(i);
}
};
template <typename...SPTR_ARGS>
void addSystems(SPTR_ARGS...args) {
m_tupleSystems = std::make_tuple(args...);
}
void run() {
m_value = 0;
runSystem<TUPLE_SIZE - 1, std::shared_ptr<ISystem<ARGS>>...>{}(m_tupleSystems, m_value);
}
private:
using TUPLE_TYPE = std::tuple<std::shared_ptr<ISystem<ARGS>>...>;
static constexpr auto TUPLE_SIZE = std::tuple_size<TUPLE_TYPE>::value;
TUPLE_TYPE m_tupleSystems;
int m_value;
};
int main() {
auto sptrSystemA = std::make_shared<SystemA>();
auto sptrSystemB = std::make_shared<SystemB>();
SystemManager<SystemA, SystemB> oSystemManager;
oSystemManager.addSystems(sptrSystemA, sptrSystemB);
oSystemManager.run();
return 0;
}
Aucun commentaire:
Enregistrer un commentaire