A vector for different classes

  • A+

I have a class with a vector I'd like to fill with one of two types of class, selected by the user. Let's call my classes option1 and option2

What I'd like to do it something like

class storage_class  { public:     storage_class(int sel, int n)     {         if(sel == 1)            for(int i = 0; i < n; i++)                 my_store.push_back(std::make_unique<option1>());             else if(sel == 2)            for(int i = 0; i < n; i++)                my_store.push_back(std::make_unique<option2>());     }  private:     // Something like this but that actually works     std::vector<T> my_store; }; 

Then I'd like to use it like this, or something similar, so there's no need to modify this usage dependent on the option chosen.

int main() {     storage_class store(1);      int n_iterations = 4;      for(int i = 0; i < n_iterations; i++)     {         store.my_store[i]->create_data();     } } 

The classes option1 and option2 will be mathematical simulations that will be creating data and themselves store this data in a vector that are members of the class.

I want to store multiple instances of either option in a vector and then manipulate them from there. I can use C++17.


As you have c++17 in use, you can simply use a std::variant as type for the container which itself can keep all types you want to have.


class A { public: void Do() { std::cout << "A::Do" << std::endl; } }; class B { public: void Go() { std::cout << "B::Go" << std::endl; } };   template<class... Ts> struct funcs : Ts... { using Ts::operator()...; }; template<class... Ts> funcs(Ts...) -> funcs<Ts...>;  int main() {     std::vector<std::variant<A,B>> vec;     vec.push_back(A{});     vec.push_back(B{});      for ( auto& el: vec)     {         std::visit( funcs{ [](A& a){ a.Do(); }, [](B& b) { b.Go(); } }, el);     } } 


A::Do B::Go 

The classes are fully independent and the methods can be simply called with std::visit and passing a callable object herein. I provide a simple funcs implementation, which simply collect all callable entities to simplify to interface the call to different methods of different unrelated classes here.

As std::variant is some kind of a tagged union, it needs the storage for the biggest type you have in use. If this wastes to much memory, you can store a pointer to the instance instead, maybe with std::unique_ptr or std::shared_ptr if you like some assistance for memory management ;)


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: