I've a container class that stores some objects of an abstract class. In some parts, the program needs to get these objects as there implementation classes. I wrote a generic get function, but it has to loop through all stored objects, which can cost a lot of time. As I know that the container will only have one object of each type I want to solve this issue during compile-time, but don't want to create my own member for each type by hand.
At the moment I don't have trouble with the "wasted" runtime, but I want to learn how to solve this.
My current implementaion:
#include <iostream>
#include <list>
class Abstract
{
public:
virtual void update() = 0;
};
class ImplA : public Abstract
{
public:
void update() {std::cout << "implA" << std::endl;}
};
class ImplB : public Abstract
{
public:
void update() {std::cout << "implB" << std::endl;}
};
class Container
{
public:
Container(){
content.push_back(new ImplA);
content.push_back(new ImplB);
}
void update() {
for (Abstract* obj : content)
obj->update();
}
template<typename T> T* get() const {
for (Abstract* obj : content) {
if(dynamic_cast<T*>(obj) != nullptr)
return dynamic_cast<T*>(obj);
}
return nullptr;
}
private:
std::list<Abstract*> content;
};
int main()
{
Container* container = new Container();
container->get<ImplA>()->update();
container->get<ImplB>()->update();
return 0;
}
My ideas on how to solve this:
Thanks in advance!
If your objects are always inserted together, then your problem has already been solved by std::tuple
:
#include <iostream>
#include <tuple>
template <class... Ts>
struct Container : std::tuple<Ts...> {
using std::tuple<Ts...>::tuple;
void update() {
std::apply([](auto &... objects){ (objects.update(), ...); }, *this);
}
};
namespace std {
template <class... Ts>
struct tuple_size<Container<Ts...>> : tuple_size<tuple<Ts...>> { };
}
template <class... Ts>
Container(Ts...) -> Container<Ts...>;
Container
supports std::get
through implicit conversion to std::tuple
and the specialization of std::tuple_size
.
See it Live on Coliru (tweaked for its pre-C++17 GCC :/)