Search code examples
c++inheritancevectorstruct

How to add derived struct elements to a vector without using pointers?


I'm working off of someone's code. There is a vector of struct P (Segment). I want to have different types of P. Therefore I defined struct P2 : P. But, since Segment takes just P and not P*, I cannot add element of type P2 to the Segment and use dynamic_cast since it will create a new element of type P and copy just i and I lose the name information.

What are my options here? Do I just have to change vector<P> to vector<P*> and adjust the code everywhere it's being used or create my own type Segment vector<P*> and use where I need it?

Also, why it was used vector<P> and not vector<P*> from the beginning since the vector can have hundreds and even thousands of elements?

struct P
{
  int i;
  P(int i2) : i(i2) {}
}

struct P2 : P
{
   string name;
   P2(string name2, int i) : P(i), name(name2) {}
}

struct P3 : P
{
  ...
}

using Segment = vector<P>;

Solution

  • You can basically use one of the following concepts:

    • Inheritance/Polymorphism: As you suggested, but then please with a std::vector<std::unique_ptr<P>>. Using a raw pointer as in vector<P*> is discouraged in modern C++, as the vector usually owns the objects. Moreover, I would then define a reasonable interface -- other than in your current example with P2.

    • Type-safe unions: For example, a std::variant<P,P2>, which can contain one of the two types. You then further need to define visitors which act specifically on the contained type.

    • Type erasure: define a common interface as a new class and map the classes to it. In the simplest version, it's just a std::function<std::string()> which captures, e.g., the parenthesis-operator of the classes. This can be thought of as inheritance without base classes.

    There's probably more approaches, but those are imo the most common ones.