J0hnD0e
J0hnD0e

Reputation: 87

Design pattern, a vector of objects, each of two possible types

I need to store objects of exactly two types in a vector, the both types have almost nothing in common.

After storing them in the vector, I want to iterate over that vector and perform an action, depending on the type.

my thoughts so far:

Both patterns seem totally clumsy to me, there is propably a total simple solution, I simply don't see.

The first type is something like this :

struct PatternMatch {
  int length;
  int indexInDict;
}

The second one:

struct NoMatch {
  std::string rawChars;
}

Upvotes: 1

Views: 154

Answers (2)

skypjack
skypjack

Reputation: 50540

If you know that you have only two types and this number won't grow in future, a C-ish tagged union is enough and easy to use:

struct PatternMatch {
  int length;
  int indexInDict;
};

struct NoMatch {
  std::string rawChars;
};

struct TaggedUnion {
  enum { MATCH, NO_MATCH } flag;
  union {
    PatternMatch match;
    NoMatch noMatch;
  };
};

Now, you can create a vector of TaggedUnions and check the flag data member to find out the actual type of each element.

Upvotes: 1

Vittorio Romeo
Vittorio Romeo

Reputation: 93274

Use boost::variant or any other "stack-based discriminated union container". I also suggest visiting the variant using lambdas.

// Either `A` or `B`.
using my_type = boost::variant<A, B>;

std::vector<my_type> my_vec;

// ...`emplace_back` stuff into `my_vec`...

auto visitor = make_lambda_visitor<void>(
    [](A&) { /* do something with A */ },
    [](B&) { /* do something with B */ }
);

for(auto& x : my_vec)
{
     boost::apply_visitor(visitor, x);
}

Note that C++17 will have std::variant.

Upvotes: 5

Related Questions