rtti

Discussion in 'C++' started by Chameleon, May 2, 2011.

  1. Chameleon

    Chameleon Guest

    Hi!
    I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    base class `Relation`.
    I want to put all of these in a `vector<Relation>` but they have
    different size, so, I create a `union AnyRelation` and I put all of
    derived classes inside this union, and the vector become
    `vector<AnyRelation>`.
    When I want to check what type the derived class is, I use `typeid`.

    Is there a better approach, or I am going right?

    Another try, is to put every derived class in its own vector:
    vector<Azimuth>
    vector<Angle>
    vector<Distance>
    and so on.
    and in a `vector<Relation>` I can use references to real objects.
    With this approach I can avoid the `typeid` because I can check if
    pointer of derived class object belongs to a specific `vector`.


    And a final question:
    Its better to create my own rtti, or to use build-in? (for speed)
    My own rtti:
    ------------
    class A {
    A() : rtti(0) {}
    int rtti;
    int getRTTI() { return rtti; }
    bool isB() { return rtti == 1; }
    virtual ~A() {}
    };
    class B : public A {
    B() { rtti = 1; }
    };
     
    Chameleon, May 2, 2011
    #1
    1. Advertising

  2. Chameleon

    Pavel Guest

    Chameleon wrote:
    > Hi!
    > I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    > base class `Relation`.
    > I want to put all of these in a `vector<Relation>` but they have
    > different size, so, I create a `union AnyRelation` and I put all of
    > derived classes inside this union, and the vector become
    > `vector<AnyRelation>`.
    > When I want to check what type the derived class is, I use `typeid`.
    >
    > Is there a better approach, or I am going right?

    Mostly theoretically, I can see a situation where the derived classes have
    different alignment from the derived class. Thus, even if the hierarchy only
    uses single inheritance, you would have to know the type before accessing the
    object in the union (and as you do it to learn the type, you have a
    chicken-and-egg issue)..
    >
    > Another try, is to put every derived class in its own vector:
    > vector<Azimuth>
    > vector<Angle>
    > vector<Distance>
    > and so on.
    > and in a `vector<Relation>` I can use references to real objects.
    > With this approach I can avoid the `typeid` because I can check if
    > pointer of derived class object belongs to a specific `vector`.

    This will work.
    >
    >
    > And a final question:
    > Its better to create my own rtti, or to use build-in? (for speed)
    > My own rtti:
    > ------------
    > class A {
    > A() : rtti(0) {}
    > int rtti;
    > int getRTTI() { return rtti; }
    > bool isB() { return rtti == 1; }
    > virtual ~A() {}
    > };
    > class B : public A {
    > B() { rtti = 1; }
    > };

    If you have virtual destructor anyway, you can save an int by defining a virtual
    instead
    virtual int getRTTI() const { return <type>; }

    Using built-in RTTI would work with less effort (although maybe with same
    performance).

    Please note I do not comment on your design because I do not know its purpose.
    Often, however, the designs directly checking the types are suspects. It's
    *usually* better make class objects do things by calling virtual functions than
    checking their types and do things with them. Again, not knowing your goal, I
    can't say with confidence this will work better in your case but you might want
    to give it a look.

    HTH,
    -Pavel
     
    Pavel, May 2, 2011
    #2
    1. Advertising

  3. Chameleon wrote:
    > Hi!
    > I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    > base class `Relation`.
    > I want to put all of these in a `vector<Relation>` but they have
    > different size, so, I create a `union AnyRelation` and I put all of
    > derived classes inside this union, and the vector become
    > `vector<AnyRelation>`.
    > When I want to check what type the derived class is, I use `typeid`.


    typeid won't help you, as you must not access any member of a union
    except for the one you put into the union. So typeid would enable you to
    store a fixed set of types in a predefined union. (Anything else would
    be an exception.) But how do you extract the classes from the union
    without accessing the wrong one?

    > Is there a better approach, or I am going right?


    Absolutely. If you really need polymorphic members in a vector, you
    won't come around using pointer or smart pointers and separate allocations.

    If you are restricted to only a few types, have a look at
    boost::variant. It addresses almost exactly what you want to do.


    > Another try, is to put every derived class in its own vector:
    > vector<Azimuth>
    > vector<Angle>
    > vector<Distance>
    > and so on.
    > and in a `vector<Relation>` I can use references to real objects.
    > With this approach I can avoid the `typeid` because I can check if
    > pointer of derived class object belongs to a specific `vector`.


    I would prefer to use a vector<Relation> that owns it's objects in some
    way (shared or not).


    > And a final question:
    > Its better to create my own rtti, or to use build-in? (for speed)
    > My own rtti:
    > ------------
    > class A {
    > A() : rtti(0) {}
    > int rtti;
    > int getRTTI() { return rtti; }
    > bool isB() { return rtti == 1; }
    > virtual ~A() {}
    > };
    > class B : public A {
    > B() { rtti = 1; }
    > };


    This will primarily create a memory overhead, since unlike you almost no
    compiler stores any RTTI per instance. As long as you use RTTI only for
    equality comparison it is most likely faster than anything you could
    write, because effectively only slots of the vtable are compared. There
    is no virtual function call and no linear memory overhead.


    Marcel
     
    Marcel Müller, May 2, 2011
    #3
  4. Chameleon

    Öö Tiib Guest

    On May 2, 5:03 am, Chameleon <> wrote:
    > I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    > base class `Relation`.
    > I want to put all of these in a `vector<Relation>` but they have
    > different size, so, I create a `union AnyRelation` and I put all of
    > derived classes inside this union, and the vector become
    > `vector<AnyRelation>`.
    >
    > When I want to check what type the derived class is, I use `typeid`.


    It is asking for difficulties. C++0x changed the union a bit but i
    still dislike it.

    > Is there a better approach, or I am going right?


    I suspect your way it won't work.

    1) More common alternatives:

    vector<boost::shared_ptr<Relation> >
    vector<tr1::unique_ptr<Relation> >

    2) Just

    vector<Relation*>

    works for those who do not want dependency on boost or C++0x
    extensions. It is more error-prone when dealing with raw pointers so
    enwrap it into something.

    3) You can remove the exposed polymorphism by using pimpl idiom so
    Relation becomes envelope class and `Angle`, `Azimuth`, `Distance`,
    `Height` are its hidden internal variants of implementation. Then
    vector<Relation> works fine.

    > Another try, is to put every derived class in its own vector:
    > vector<Azimuth>
    > vector<Angle>
    > vector<Distance>
    > and so on.


    That loses polymorphism over common interface Relation and you will
    have several containers to manage.

    > and in a `vector<Relation>` I can use references to real objects.


    References can not be stored in vector. Also you should avoid storing
    iterators or references or pointers to elements of vector. These get
    invalid if you insert, erase or push_back into vector.

    > With this approach I can avoid the `typeid` because I can check if
    > pointer of derived class object belongs to a specific `vector`.
    >
    > And a final question:
    > Its better to create my own rtti, or to use build-in? (for speed)
    > My own rtti:
    > ------------
    > class A {
    >         A() : rtti(0) {}
    >         int rtti;
    >         int getRTTI() { return rtti; }
    >         bool isB() { return rtti == 1; }
    >         virtual ~A() {}};
    >
    > class B : public A {
    >         B() { rtti = 1; }
    > };


    Nah ... avoid magic numbers and avoid writing things yourself that are
    present in language. The people writing compilers are way over average
    skilled and their user base is large so their defects will be most
    likely discovered and fixed before your software reaches your end
    users.

    Use built-in RTTI when you need to. Beware that you should avoid
    directly using RTTI as lot you can. Using RTTI too lot indicates weak
    design. dynamic_cast can be useful for acquiring (or checking
    presence of) other interfaces when having an interface pointer. For
    typeid there are too few good use cases besides debugging and
    troubleshooting.
     
    Öö Tiib, May 2, 2011
    #4
  5. Chameleon

    Chameleon Guest

    Στις 02 Μαϊ 2011 14:05, ο/η Öö Tiib έγÏαψε:
    > On May 2, 5:03 am, Chameleon<> wrote:
    >> I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    >> base class `Relation`.
    >> I want to put all of these in a `vector<Relation>` but they have
    >> different size, so, I create a `union AnyRelation` and I put all of
    >> derived classes inside this union, and the vector become
    >> `vector<AnyRelation>`.
    >>
    >> When I want to check what type the derived class is, I use `typeid`.

    >
    > It is asking for difficulties. C++0x changed the union a bit but i
    > still dislike it.
    >
    >> Is there a better approach, or I am going right?

    >
    > I suspect your way it won't work.
    >
    > 1) More common alternatives:
    >
    > vector<boost::shared_ptr<Relation> >
    > vector<tr1::unique_ptr<Relation> >
    >
    > 2) Just
    >
    > vector<Relation*>
    >


    Create large number of small individual objects in heap is overhead.
    It sounds like Java to me.

    > works for those who do not want dependency on boost or C++0x
    > extensions. It is more error-prone when dealing with raw pointers so
    > enwrap it into something.
    >
    > 3) You can remove the exposed polymorphism by using pimpl idiom so
    > Relation becomes envelope class and `Angle`, `Azimuth`, `Distance`,
    > `Height` are its hidden internal variants of implementation. Then
    > vector<Relation> works fine.


    My approach a little bit similar:
    Every of 5 derived classes in its own vector. (Instead of every single
    object in a new block in heap)
    A big vector with envelope class for derived classes implementing the
    operator* to access base class which has the complete functionality.
    Envelope class has the type of derivative class and the index in its vector.

    The problem is that I cannot use only one derived class to do something,
    but different derived classes together. E.g. Distance and Angle (to
    describe a new point) or angle and angle, or distance and distance and
    clockwise.

    And after I will use all of these as springs linear (Distance, Height)
    or angular (Angle, Azimuth) to minimize the error.

    >> Another try, is to put every derived class in its own vector:
    >> vector<Azimuth>
    >> vector<Angle>
    >> vector<Distance>
    >> and so on.

    >
    > That loses polymorphism over common interface Relation and you will
    > have several containers to manage.
    >
    >> and in a `vector<Relation>` I can use references to real objects.

    >
    > References can not be stored in vector. Also you should avoid storing
    > iterators or references or pointers to elements of vector. These get
    > invalid if you insert, erase or push_back into vector.
     
    Chameleon, May 2, 2011
    #5
  6. Chameleon

    James Kanze Guest

    On May 2, 3:03 am, Chameleon <> wrote:

    > I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    > base class `Relation`.
    > I want to put all of these in a `vector<Relation>` but they have
    > different size, so, I create a `union AnyRelation` and I put all of
    > derived classes inside this union, and the vector become
    > `vector<AnyRelation>`.
    > When I want to check what type the derived class is, I use `typeid`.


    > Is there a better approach, or I am going right?


    Well, there's one major problem with your approach. It isn't
    legal C++, and won't compile. At least assuming that Relation
    has any virtual functions (and it should, otherwise, there's no
    point in the derivation). What you can do is use something like
    boost::variant, or even boost::any, but usually (not always),
    the need for such a solution is indicative of a design error.

    > Another try, is to put every derived class in its own vector:
    > vector<Azimuth>
    > vector<Angle>
    > vector<Distance>
    > and so on.
    > and in a `vector<Relation>` I can use references to real objects.
    > With this approach I can avoid the `typeid` because I can check if
    > pointer of derived class object belongs to a specific `vector`.


    The real question is what you are doing with the typeid to begin
    with. You've not described the problem in enough detail, or
    rather at a high enough level, for us to make any concrete
    suggestions, but in most cases, if Azimuth implements Relation,
    client code should be able to deal with just Relation, without
    knowing that this particular Relation is an Azimuth. (Again,
    there are exceptions, but they are few and far between. And
    generally only concern a single subset of the derived classes.)

    > And a final question:
    > Its better to create my own rtti, or to use build-in? (for speed)
    > My own rtti:
    > ------------
    > class A {
    > A() : rtti(0) {}
    > int rtti;
    > int getRTTI() { return rtti; }
    > bool isB() { return rtti == 1; }
    > virtual ~A() {}};


    > class B : public A {
    > B() { rtti = 1; }
    > };


    In general, it's better to only use virtual functions. If some
    of the derived classes have to implement an extended interface,
    then I'd probably go with dynamic_cast until the profiler showed
    it to be a problem. If it is a performance problem, and the
    design really does require such, then you can consider something
    like:

    class Base
    {
    // ...
    virtual Extended* getExtended() { return NULL; }
    // ...
    };

    class Extended : public Base
    {
    virtual Extended* getExtended() { return this; }
    // ...
    };

    Those classes which implement the extended interface derived
    from Extended; those which don't, don't.

    And for better or for worse, once polymorphism enters into the
    scene, you're going to have to deal with pointers and dynamic
    allocation. Since, based on the names, I'd guess that these are
    really "value" type objects (which you'ld copy, and never
    allocate dynamically if the polymorphism wasn't involved), and
    they probably don't contain pointers to other objects (so you
    can't get cycles), you can consider using some sort of reference
    counting pointer; boost::shared_ptr, or better yet, some sort of
    invasive pointer (and have Relation contain the counter);
    alternatively, if you make all of the constructors private,
    use factory methods which return the smart pointers, and none of
    the types ever call any function which might take a pointer to
    the object itself, you can probably use boost::shared_ptr
    without too many problems.

    --
    James Kanze
     
    James Kanze, May 2, 2011
    #6
  7. Chameleon

    James Kanze Guest

    On May 2, 9:00 pm, Chameleon <> wrote:
    > Στις 02 Μαϊ 2011 14:05, ο/η Öö Tiib έγÏαψε:
    > > On May 2, 5:03 am, Chameleon<> wrote:
    > >> I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    > >> base class `Relation`.
    > >> I want to put all of these in a `vector<Relation>` but they have
    > >> different size, so, I create a `union AnyRelation` and I put all of
    > >> derived classes inside this union, and the vector become
    > >> `vector<AnyRelation>`.


    > >> When I want to check what type the derived class is, I use `typeid`.


    > > It is asking for difficulties. C++0x changed the union a bit but i
    > > still dislike it.


    > >> Is there a better approach, or I am going right?


    > > I suspect your way it won't work.


    > > 1) More common alternatives:


    > > vector<boost::shared_ptr<Relation> >
    > > vector<tr1::unique_ptr<Relation> >


    > > 2) Just


    > > vector<Relation*>


    > Create large number of small individual objects in heap is overhead.
    > It sounds like Java to me.


    The reason Java works like this is that it more or less assumes
    (or almost requires) that every object is polymorphic. From
    what you've described, that's the case you're in. As soon as
    polymorphism comes into play, C++ starts allocating dynamically
    as well.

    > > works for those who do not want dependency on boost or C++0x
    > > extensions. It is more error-prone when dealing with raw
    > > pointers so enwrap it into something.


    There are very few things as error prone as boost::shared_ptr.
    At least for the sort of things one usually allocates
    dynamically; his case may be the exception (but he's not told us
    enough about the derived types to be sure).

    > > 3) You can remove the exposed polymorphism by using pimpl idiom so
    > > Relation becomes envelope class and `Angle`, `Azimuth`, `Distance`,
    > > `Height` are its hidden internal variants of implementation. Then
    > > vector<Relation> works fine.


    But he still ends up with a lot of small allocations:).

    From the names, I suspect that a single class, with a
    discriminator indicating how to interpret the contents, and
    perhaps a union with the actual data, might be appropriate.
    Might be---one really can't say without knowing more about the
    applications.

    > My approach a little bit similar:
    > Every of 5 derived classes in its own vector. (Instead of every single
    > object in a new block in heap)
    > A big vector with envelope class for derived classes implementing the
    > operator* to access base class which has the complete functionality.
    > Envelope class has the type of derivative class and the index in its vector.


    > The problem is that I cannot use only one derived class to do something,
    > but different derived classes together. E.g. Distance and Angle (to
    > describe a new point) or angle and angle, or distance and distance and
    > clockwise.


    > And after I will use all of these as springs linear (Distance, Height)
    > or angular (Angle, Azimuth) to minimize the error.


    I'm not sure I've understood what you're trying to do, so this
    might be complete rubish, but it vaguely sounds like you're
    trying to maintain a position (relative or absolute?) in several
    different formats. The usual solution here is to unify the
    format inside the class, and add manupulators along the lines of
    changeAzimut, etc.

    --
    James Kanze
     
    James Kanze, May 3, 2011
    #7
  8. Chameleon <> wrote:
    > Create large number of small individual objects in heap is overhead.


    Sometimes you simply don't have a choice. Dynamic polymorphism usually
    means that you must allocate on the heap. Depending on how often and
    how many you need to do it, the overhead may well be inconsequential.
     
    Juha Nieminen, May 3, 2011
    #8
  9. Chameleon

    Öö Tiib Guest

    On May 3, 2:09 am, James Kanze <> wrote:
    > On May 2, 9:00 pm, Chameleon <> wrote:
    > > Στις 02 Μαϊ 2011 14:05, ο/η Öö Tiib έγÏαψε:
    > > > On May 2, 5:03 am, Chameleon<>  wrote:
    > > >> I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    > > >> base class `Relation`.
    > > >> I want to put all of these in a `vector<Relation>` but they have
    > > >> different size, so, I create a `union AnyRelation` and I put all of
    > > >> derived classes inside this union, and the vector become
    > > >> `vector<AnyRelation>`.
    > > >> When I want to check what type the derived class is, I use `typeid`.
    > > > It is asking for difficulties. C++0x changed the union a bit but i
    > > > still dislike it.
    > > >> Is there a better approach, or I am going right?
    > > > I suspect your way it won't work.
    > > > 1) More common alternatives:
    > > >   vector<boost::shared_ptr<Relation>  >
    > > >   vector<tr1::unique_ptr<Relation>  >
    > > > 2) Just
    > > >   vector<Relation*>

    > > Create large number of small individual objects in heap is overhead.
    > > It sounds like Java to me.

    >
    > The reason Java works like this is that it more or less assumes
    > (or almost requires) that every object is polymorphic.  From
    > what you've described, that's the case you're in.  As soon as
    > polymorphism comes into play, C++ starts allocating dynamically
    > as well.


    The whole concern about small allocations sounds a bit premature for
    me. Marcel Müller suggested something like:

    vector<boost::variant<Angle, Azimuth, Distance, Height>

    That will not allocate lot of small objects. My experience is that
    boost::variant does not also fit for polymorphic classes (but is
    certainly better than union).

    > > > works for those who do not want dependency on boost or C++0x
    > > > extensions. It is more error-prone when  dealing with raw
    > > > pointers so enwrap it into something.

    >
    > There are very few things as error prone as boost::shared_ptr.
    > At least for the sort of things one usually allocates
    > dynamically; his case may be the exception (but he's not told us
    > enough about the derived types to be sure).


    I am not sure why shared_ptr is error prone. It is a tool like any
    other tool and it is *wrong* to use it at numerous places. Who knows
    how it is for OP's problem. Thats why i gave several options. If it
    fits the design then i would use shared_ptr instead of raw pointer.

    > > > 3) You can remove the exposed polymorphism by using pimpl idiom so
    > > > Relation becomes envelope class and  `Angle`, `Azimuth`, `Distance`,
    > > > `Height` are its hidden internal variants of implementation. Then
    > > > vector<Relation>  works fine.

    >
    > But he still ends up with a lot of small allocations:).


    If it becomes concern then OP may use boost::pool for fast dynamic
    allocations (with pimpl it works great) also he can use other nice
    optimizations with pimpl (like lazy copy-on-write).

    > From the names, I suspect that a single class, with a
    > discriminator indicating how to interpret the contents, and
    > perhaps a union with the actual data, might be appropriate.
    > Might be---one really can't say without knowing more about the
    > applications.


    Yes, that is also possibility. It can however result with hard-to-
    maintain C-style switch-case polymorphism in unskilled hands. I would
    first try to move real polymorphism to implementation detail.
     
    Öö Tiib, May 3, 2011
    #9
  10. Chameleon

    Öö Tiib Guest

    On May 2, 11:00 pm, Chameleon <> wrote:
    > Στις 02 Μαϊ 2011 14:05, ο/η Öö Tiib έγÏαψε:
    >
    > > 3) You can remove the exposed polymorphism by using pimpl idiom so
    > > Relation becomes envelope class and  `Angle`, `Azimuth`, `Distance`,
    > > `Height` are its hidden internal variants of implementation. Then
    > > vector<Relation>  works fine.

    >
    > My approach a little bit similar:
    > Every of 5 derived classes in its own vector. (Instead of every single
    > object in a new block in heap)
    > A big vector with envelope class for derived classes implementing the
    > operator* to access base class which has the complete functionality.
    > Envelope class has the type of derivative class and the index in its vector.


    The "own vectors" in your design sound like custom memory management.
    If so then use things designed for memory management like boost::pool.

    > The problem is that I cannot use only one derived class to do something,
    > but different derived classes together. E.g. Distance and Angle (to
    > describe a new point) or angle and angle, or distance and distance and
    > clockwise.
    >
    > And after I will use all of these as springs linear (Distance, Height)
    > or angular (Angle, Azimuth) to minimize the error.


    It feels that the Distance, Height, Angle and Azimuth are not
    descendants of generic Relation (that "does something") but its
    possible components. So actually you should have LinearRelation and
    AngularRelation derived from Relation?
     
    Öö Tiib, May 3, 2011
    #10
  11. Chameleon

    James Kanze Guest

    On May 3, 10:41 am, Öö Tiib <> wrote:
    > On May 3, 2:09 am, James Kanze <> wrote:
    > > On May 2, 9:00 pm, Chameleon <> wrote:
    > > > Στις 02 Μαϊ 2011 14:05, ο/η Öö Tiib έγÏαψε:
    > > > > On May 2, 5:03 am, Chameleon<> wrote:
    > > > >> I have derived classes `Angle`, `Azimuth`, `Distance`, `Height` from
    > > > >> base class `Relation`.
    > > > >> I want to put all of these in a `vector<Relation>` but they have
    > > > >> different size, so, I create a `union AnyRelation` and I put all of
    > > > >> derived classes inside this union, and the vector become
    > > > >> `vector<AnyRelation>`.
    > > > >> When I want to check what type the derived class is, I use `typeid`.
    > > > > It is asking for difficulties. C++0x changed the union a bit but i
    > > > > still dislike it.
    > > > >> Is there a better approach, or I am going right?
    > > > > I suspect your way it won't work.
    > > > > 1) More common alternatives:
    > > > > vector<boost::shared_ptr<Relation> >
    > > > > vector<tr1::unique_ptr<Relation> >
    > > > > 2) Just
    > > > > vector<Relation*>
    > > > Create large number of small individual objects in heap is overhead.
    > > > It sounds like Java to me.


    > > The reason Java works like this is that it more or less assumes
    > > (or almost requires) that every object is polymorphic. From
    > > what you've described, that's the case you're in. As soon as
    > > polymorphism comes into play, C++ starts allocating dynamically
    > > as well.


    > The whole concern about small allocations sounds a bit premature for
    > me.


    Agreed.

    > Marcel Müller suggested something like:


    > vector<boost::variant<Angle, Azimuth, Distance, Height>


    > That will not allocate lot of small objects. My experience is that
    > boost::variant does not also fit for polymorphic classes (but is
    > certainly better than union).


    Another name for "variant" is discriminate union:). The
    original poster had them all deriving from a common base class,
    so I assumed polymorphism, but depending on the design, a
    discriminate union could be a valid alternative. (But one or
    the other: if you use boost::variant, there's no sense in
    keeping the common base class.)

    > > > > works for those who do not want dependency on boost or C++0x
    > > > > extensions. It is more error-prone when dealing with raw
    > > > > pointers so enwrap it into something.


    > > There are very few things as error prone as boost::shared_ptr.
    > > At least for the sort of things one usually allocates
    > > dynamically; his case may be the exception (but he's not told us
    > > enough about the derived types to be sure).


    > I am not sure why shared_ptr is error prone.


    It's too easy to end up with the memory being deleted too soon,
    because you've made a shared_ptr twice from the same raw
    pointer, or to end up with memory leaks, because of cycles.

    > It is a tool like any other tool and it is *wrong* to use it
    > at numerous places. Who knows how it is for OP's problem.
    > Thats why i gave several options. If it fits the design then i
    > would use shared_ptr instead of raw pointer.


    Used like that, with an understanding of its weaknesses, it's a
    very effective tool; I use it myself in such cases. (More
    often, I'll use my own reference counted pointer, however.
    Simply because I had it and was using it before boost came
    along, and I'm used to it.) But because it's so often
    recommended as a silver bullet, to be used automatically without
    thinking, one feels obliged to repeat the usual warnings.

    > > > > 3) You can remove the exposed polymorphism by using pimpl idiom so
    > > > > Relation becomes envelope class and `Angle`, `Azimuth`, `Distance`,
    > > > > `Height` are its hidden internal variants of implementation. Then
    > > > > vector<Relation> works fine.


    > > But he still ends up with a lot of small allocations:).


    > If it becomes concern then OP may use boost::pool for fast dynamic
    > allocations (with pimpl it works great) also he can use other nice
    > optimizations with pimpl (like lazy copy-on-write).


    A lot of implementations of malloc will in fact use a pool
    allocator for small allocations. The real point is (and I'm
    sure you agree): don't worry about it until it is a problem (if
    it ever is), and then solve the exact problem, based on profiler
    output.

    > > From the names, I suspect that a single class, with a
    > > discriminator indicating how to interpret the contents, and
    > > perhaps a union with the actual data, might be appropriate.
    > > Might be---one really can't say without knowing more about the
    > > applications.


    > Yes, that is also possibility. It can however result with hard-to-
    > maintain C-style switch-case polymorphism in unskilled hands.


    In unskilled hands, polymorphism can also result in hard to
    maintain code:). This suggestion is really just a simplified
    variant of the boost::variant solution; in both, you have to
    deal with a switch (or chained else/if, or possibly, a
    map<pair<TypeId, TypeId>, someFunctionType>). Usually (based on
    my experience, at least), polymorphism will result in a cleaner
    solution, but there are exceptions.

    --
    James Kanze
     
    James Kanze, May 3, 2011
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Harrison

    Re: RTTI

    John Harrison, Jul 14, 2003, in forum: C++
    Replies:
    2
    Views:
    467
    John Harrison
    Jul 14, 2003
  2. Alf P. Steinbach

    Re: RTTI

    Alf P. Steinbach, Jul 14, 2003, in forum: C++
    Replies:
    0
    Views:
    477
    Alf P. Steinbach
    Jul 14, 2003
  3. Steven Lien

    About RTTI

    Steven Lien, Aug 19, 2003, in forum: C++
    Replies:
    4
    Views:
    614
    Ivan Vecerina
    Aug 19, 2003
  4. BillyO
    Replies:
    2
    Views:
    500
    dslater
    Sep 30, 2003
  5. tirath
    Replies:
    3
    Views:
    726
    Ivan Vecerina
    Oct 12, 2003
Loading...

Share This Page