Thread: Heterogeneous container having unique instances of each type

  1. #1
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094

    Heterogeneous container having unique instances of each type

    Hello fellow programmers,

    Some may know me from the C part of the forum where I tend to post more often. In this case, I am in need of some guidance regarding a C++ issue that has come up lately in one of my projects. I have researched previous forum postings regarding similar issues but I didn't find any thread addressing this one in particular.

    The issue I am having is a design one rather than a coding one, so I am just looking for ideas on how to tackle the problem not code itself. Since I cannot actually post my code here, I will provide a similar abstraction of my problem below.

    Let's say that I have an abstract class called Dimension which is derived by three other classes A, B and C. Dimension just contains 2 pure virtual methods which need to be implemented by derived classes. Now, another class, called Monitor needs to manage a collection of Dimension derived classes.

    One major requirement however is that this code is easily extended to include additional user programmer defined Dimension derived classes and as such, the Monitor class can only interface with the Dimension objects in its collection through the two methods declared by class Dimension, and implemented by its derived classes.

    Now, normally that could easily be represented by having an STL container of Dimension* objects and then using polymorphism to call the appropriate method in the derived class. That is pretty much C++ Polymorphism 101, however, here is the twist in this case: the collection of Dimensions in the Monitor class has to have unique types. Therefore, for instance, you cannot have 2 A class types in that collection, but you can have any combination of derived classes which includes just one instance of each class type.

    My questions is: is there a design flaw here, or is there a solution to address this problem in a c++ environment?

    Thanks in anticipation,
    Claudiu
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  2. #2
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    So the thing you need to do is have the code prevent the caller from adding an item that is the same type as an item already inside the Monitor?
    Is using C++ rtti an option?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #3
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    RTTI is definitely an option that I have considered. The question is would that add too much overhead in comparing a newly added item to the container to existing item types to make that feasible?
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The reason not to use RTTI is not only performance but design. The use of RTTI requires a hard-coded class name to be used. Any time you must ask an object '...what specific type are you?...' your design should throw up red flags all over the place. The whole point of programming to an interface is so that no entity needs to know the exact type of an object.

    One major requirement however is that this code is easily extended to include additional user programmer defined Dimension derived classes and as such, the Monitor class can only interface with the Dimension objects in its collection through the two methods declared by class Dimension
    In other words Monitor only has the interface view of Dimension and thus only the two virtual methods in it. The only way to provide different visibility is through a static or dynamic cast to the derived type or interface. You can use static cast if you make clear the agreement between the system and the client using it that the type used in the cast is derived from Dimension. A safer yet slower cast would be to use dynamic_cast which would fail if the object was not a Dimension derived type.

    So you can provide a template method in the container class to hide the cast yet also create an agreement between the code using the derived Dimension type and the container that contains the Dimension types. Essentially if a programmer specifies a type in the templated method it is understood that they are saying the specific type derives from Dimension. If you do not feel comfortable with this agreement you can force it by using dynamic_cast<> with the understanding that the cast should be performed at startup or initialization, cached off, and thus only be performed a minimal number of times. Alternatively you could simply not provide any method in your container to cast the object which would place the responsibility of the usage of the object on the programmer using the container which is probably the best option and limits the scope of the container class to what it should be.

    Note that you can 'bring in' other interfaces when creating your Dimension derived type and then cast to those interfaces to change the visiblity into the object.
    Code:
    class IObjectInterfaceOne
    {
        public:
           virtual ~IObjectInterfaceOne() { }
           virtual void Foo() = 0;
    };
    
    class IObjectInterfaceTwo
    {
        public:
           virtual ~IObjectInterfaceTwo() { }
           virtual void Bar() = 0;
    };
    
    class SomeObject : public IObjectInterfaceOne, public IObjectInterfaceTwo
    {
        public:
          SomeObject();
          virtual ~SomeObject();
    
          virtual void Foo();
          virtual void Bar();
    };
    
    SomeObject *pObject = new SomeObject();
    IObjectInterfaceOne *pInterfaceOne = dynamic_cast<IObjectInterfaceOne *>(pObject);
    IObjectInterfaceTwo *pInterfaceTwo = dynamic_cast<IObjectInterfaceTwo *>(pObject);
    
    pInterfaceOne->Foo();
    pInterfaceTwo->Bar();
    Here pInterfaceOne can only access Foo() and pInterfaceTwo can only access Bar() while pObject can access both. So you could have a container of IObjectInterfaceOne objects and a container of IObjectInterfaceTwo objects or you could provide a method in SomeObject that would return the object as type IObjectInterfaceOne or IObjectInterfaceTwo.

    So to answer your question other programmers can bring in interfaces and cast to said interfaces to use whichever one they want. But from the standpoint of the container it must view all objects as Dimension type objects.

    Usually it is best not to do this. The idea is that all objects adhere to the interface and one could argue that if they add to the interface then they do not 100% adhere to it and thus do not belong in the container. An argument for it is when you have many objects that may change the interface but do not have multiple instances of those objects in which case you would have several containers of objects that only contained 1 object.
    Last edited by VirtualAce; 08-07-2011 at 01:38 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 05-14-2011, 09:26 PM
  2. need help using unique and counting instances of a number
    By go_loco in forum C++ Programming
    Replies: 18
    Last Post: 03-30-2010, 01:00 PM
  3. stl container to store more than 1 type
    By sujeet1 in forum C++ Programming
    Replies: 7
    Last Post: 05-09-2007, 04:10 AM
  4. Replies: 4
    Last Post: 03-21-2004, 03:34 PM
  5. list container type
    By minesweeper in forum C++ Programming
    Replies: 3
    Last Post: 12-12-2002, 02:22 PM