Search code examples
c++inheritancedata-structuresdeque

How to extract from a deque without casting?


I have 5 classes that called operators :

 * Enter(x)
 * Exit(x)
 * Push(b,x,y)
 * TurnOn(x)
 * TurnOff(x)

And 3 more classes that are called Predicates :

 * At(x,y) - example : At(Robot,Room3) , At(Box1,Room1) , At(Box3,Corridor)
 * SwithOn(x) - SwitchOn(Room2)
 * SwitchOff(x) - SwitchOff(Room1) , SwitchOff(Room4)

And I want to have good data structure the store them .

At first, I created two base classes and used inheritance:

  • Class Predicate for At(x,y) , SwithOn(x) and SwitchOff(x)

  • Class Operator for Enter(x) , Exit(x) , Push(b,x,y) , TurnOn(x) , TurnOff(x) .

And I added two deques :

std::deque<Operator> operators;
std::deque<Predicate> predicates;

And then ,when I create for instance a Exit operator :

Exit myExit ;

and push it into the the deque :

operators.push_back(myExit); // this works fine 

But I when I'd try to extract some kind of element from operators deuqe , I'd have to use some kind of casting .

  1. Is it possible to have a data structure that can store multiple (different types) objects ?

  2. I'm still at the stage of the planning , can you suggest maybe some other kind of design so I won't have problems with extracting elements ? the best thing I can think of is polymorphism ...

Regards


Solution

  • For your specific requirements I would look at making the Operator polymorphic and store the data in a boost pointer containers like ptr_vector. After all, it makes sense that the various specific operations all have in common that they are operators.

    Your current implementation with the basic std::deque<> will lead to object slicing as you're only storing the base class, so that's not going to work. In this particular case where polymorphism is desired, you really need to be able to store a pointer to the object instead. In your case, you probably want to use a

    boost::ptr_vector<Operator> something;
    

    If you can't use boost, the other option is to use a standard container with something like a std::shared_ptr, for example like this:

    std::deque<std::shared_ptr<Operator> > something;
    

    You don't want to store raw pointers in a std::vector as that leads to all sorts of interesting lifetime management issues that are easily avoided.