Dynamic polymorphism vs. Static polymorphism

Discussion in 'C++' started by Krivenok Dmitry, May 30, 2006.

  1. Hello all!

    Perhaps the most important feature of dynamic polymorphism is
    ability to handle heterogeneous collections of objects.
    ("C++ Templates: The Complete Guide" by David Vandevoorde
    and Nicolai M. Josuttis. Chapter 14.)

    How to implement analogue of this technique via static polymorphism?
    Perhaps there is special design pattern for this purpose...

    Thanks!
     
    Krivenok Dmitry, May 30, 2006
    #1
    1. Advertising

  2. Krivenok Dmitry wrote:
    > Hello all!
    >
    > Perhaps the most important feature of dynamic polymorphism is
    > ability to handle heterogeneous collections of objects.
    > ("C++ Templates: The Complete Guide" by David Vandevoorde
    > and Nicolai M. Josuttis. Chapter 14.)
    >
    > How to implement analogue of this technique via static polymorphism?
    > Perhaps there is special design pattern for this purpose...



    There are many concept that are called polymorphism or genericity:
    http://en.wikipedia.org/wiki/Polymorphism_(computer_science)

    Which ones do you mean (especially with "static polymorphism") exactly?
     
    Ulrich Hobelmann, May 30, 2006
    #2
    1. Advertising

  3. Krivenok Dmitry

    mlimber Guest

    Ulrich Hobelmann wrote:
    > Krivenok Dmitry wrote:
    > > Hello all!
    > >
    > > Perhaps the most important feature of dynamic polymorphism is
    > > ability to handle heterogeneous collections of objects.
    > > ("C++ Templates: The Complete Guide" by David Vandevoorde
    > > and Nicolai M. Josuttis. Chapter 14.)
    > >
    > > How to implement analogue of this technique via static polymorphism?
    > > Perhaps there is special design pattern for this purpose...

    >
    >
    > There are many concept that are called polymorphism or genericity:
    > http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
    >
    > Which ones do you mean (especially with "static polymorphism") exactly?


    He means C++ templates, but the question is too broad to be answered
    completely here. One could implement static polymorphism like this:

    struct A
    {
    int Read(); // Does something
    };

    struct B
    {
    int Read(); // Does something else
    };

    template <class T>
    class Reader
    {
    T& t_;
    public:
    Reader( T& t ) : t_( t ) {}

    int DoSomething()
    {
    return t.Read();
    }
    };

    This template is basically the same as using an abstract base class
    with a virtual Read(), but it achieves the same effect without
    virtuality, which can sometimes be useful.

    Cheers! --M
     
    mlimber, May 30, 2006
    #3
  4. Krivenok Dmitry

    Alan Johnson Guest

    Krivenok Dmitry wrote:
    > Hello all!
    >
    > Perhaps the most important feature of dynamic polymorphism is
    > ability to handle heterogeneous collections of objects.
    > ("C++ Templates: The Complete Guide" by David Vandevoorde
    > and Nicolai M. Josuttis. Chapter 14.)
    >
    > How to implement analogue of this technique via static polymorphism?
    > Perhaps there is special design pattern for this purpose...
    >
    > Thanks!
    >


    What is the goal you are trying to accomplish?

    If I had to guess, you are either trying to create some sort of compile
    time container, or a run time container that supports heterogenous
    types. In the former case, some variation on the type lists may be what
    you want (see <url: http://www.ddj.com/dept/cpp/184403813>). In the
    latter case, well, that isn't something that compile time polymorphism
    can do for you. If the types you want to store have the same interface,
    then use run time polymorphism. That is why it exists. If they don't,
    then some form of discriminated union may do what you want.

    --
    Alan Johnson
     
    Alan Johnson, May 30, 2006
    #4
  5. Krivenok Dmitry

    Noah Roberts Guest

    mlimber wrote:

    > This template is basically the same as using an abstract base class
    > with a virtual Read(), but it achieves the same effect without
    > virtuality, which can sometimes be useful.


    I have to debate that statement and say they are completely different.
    Dynamic vs. Static polymorphism do completely different things
    resulting in vastly different behavior. One simple example:

    struct Abstract { virtual void f() = 0; }

    struct A : Abstract { void f() {} };
    struct B : Abstract { void f() {} };

    void fun(Abstract * a) { a->f(); }

    vs.

    struct A { void f(); }
    struct B { void f(); }

    template <typename A>
    void fun(A * a) { a->f(); }

    Note how these two behave completely differently. One has a single
    function that allows pointers of any of the three types to be passed in
    and calls the appropriate implementation of f() for the input. The
    other creates two completely different functions that accept completely
    unrelated inputs; it only looks similar to the programmer. This is a
    very important distinction; they are actually not the same at all.
     
    Noah Roberts, May 30, 2006
    #5
  6. Krivenok Dmitry

    mlimber Guest

    Noah Roberts wrote:
    > mlimber wrote:
    >
    > > This template is basically the same as using an abstract base class
    > > with a virtual Read(), but it achieves the same effect without
    > > virtuality, which can sometimes be useful.

    >
    > I have to debate that statement and say they are completely different.
    > Dynamic vs. Static polymorphism do completely different things
    > resulting in vastly different behavior. One simple example:
    >
    > struct Abstract { virtual void f() = 0; }
    >
    > struct A : Abstract { void f() {} };
    > struct B : Abstract { void f() {} };
    >
    > void fun(Abstract * a) { a->f(); }
    >
    > vs.
    >
    > struct A { void f(); }
    > struct B { void f(); }
    >
    > template <typename A>
    > void fun(A * a) { a->f(); }
    >
    > Note how these two behave completely differently. One has a single
    > function that allows pointers of any of the three types to be passed in
    > and calls the appropriate implementation of f() for the input. The
    > other creates two completely different functions that accept completely
    > unrelated inputs; it only looks similar to the programmer. This is a
    > very important distinction; they are actually not the same at all.


    I apologize for my imprecision. My point was that they are the same in
    the sense that both invoke a function without knowing any further
    implementation details. Certainly there are other differences between
    these two types of polymorphism.

    Cheers! --M
     
    mlimber, May 30, 2006
    #6
  7. Krivenok Dmitry

    Cy Edmunds Guest

    "Krivenok Dmitry" <> wrote in message
    news:...
    > Hello all!
    >
    > Perhaps the most important feature of dynamic polymorphism is
    > ability to handle heterogeneous collections of objects.
    > ("C++ Templates: The Complete Guide" by David Vandevoorde
    > and Nicolai M. Josuttis. Chapter 14.)
    >
    > How to implement analogue of this technique via static polymorphism?
    > Perhaps there is special design pattern for this purpose...
    >
    > Thanks!
    >


    All elements of a container must be of the same type. If it is a pointer or
    smart pointer to a common base class we have dynamic polymorphism. Static
    polymorphism can be accomplished using a flag to determine the actual type:

    struct clumsy
    {
    int flag;
    union (...} other_stuff;
    };

    You can have an array of these but you must set the flag to the right value
    for each type of data stored in the union and go through a switch or similar
    logic structure every time you use it. If you want to add a new type to the
    union you have to find all the logic structures and update them, so this
    scheme is not very maintainable.

    A variation on this theme is:

    struct bummer
    {
    int flag;
    };

    struct radical
    {
    int flag;
    double value;
    };

    radical r;
    r.flag = 2;
    r.value = 76.3;
    bummer *p = (bummer*) &r;

    Now you can have an array of bummer pointers, check the flag, and cast to
    the actual type. This has all the problems of the union version but might
    save a little memory in some cases I suppose.

    Void pointers offer a sort of static polymorphism. I sometimes use them at C
    interfaces where they are actually pointing to C++ classes. If you cast
    carefully that can work.

    Also see boost::any.

    All and all when I look over these alternatives I certainly appreciate
    dynamic polymorphism.

    Cy
     
    Cy Edmunds, May 31, 2006
    #7
  8. Krivenok Dmitry

    Luke Meyers Guest

    Cy Edmunds wrote:
    > "Krivenok Dmitry" <> wrote in message
    > All elements of a container must be of the same type. If it is a pointer or
    > smart pointer to a common base class we have dynamic polymorphism. Static
    > polymorphism can be accomplished using a flag to determine the actual type:
    >
    > struct clumsy
    > {
    > int flag;
    > union (...} other_stuff;
    > };


    Uh, I'm pretty sure this is not what most people mean by "static
    polymorphism." How did you come to associate the term with this ugly
    scheme?

    The "static"/"dynamic" distinction wrt polymorphism, as with e.g.
    typing, refers to compile-time vs. run-time. With static polymorphism,
    the actual type of the object is known at compile-time. The usual
    (only?) mechanism in C++ for this is templates.

    Luke
     
    Luke Meyers, May 31, 2006
    #8
  9. Krivenok Dmitry

    Cy Edmunds Guest

    "Luke Meyers" <> wrote in message
    news:...
    > Cy Edmunds wrote:
    >> "Krivenok Dmitry" <> wrote in message
    >> All elements of a container must be of the same type. If it is a pointer
    >> or
    >> smart pointer to a common base class we have dynamic polymorphism. Static
    >> polymorphism can be accomplished using a flag to determine the actual
    >> type:
    >>
    >> struct clumsy
    >> {
    >> int flag;
    >> union (...} other_stuff;
    >> };

    >
    > Uh, I'm pretty sure this is not what most people mean by "static
    > polymorphism." How did you come to associate the term with this ugly
    > scheme?
    >
    > The "static"/"dynamic" distinction wrt polymorphism, as with e.g.
    > typing, refers to compile-time vs. run-time. With static polymorphism,
    > the actual type of the object is known at compile-time. The usual
    > (only?) mechanism in C++ for this is templates.
    >
    > Luke
    >


    The original poster asked about heterogeneous containers. How would you do
    that with templates?

    Cy
     
    Cy Edmunds, May 31, 2006
    #9
  10. Krivenok Dmitry

    Axter Guest

    Cy Edmunds wrote:
    > "Luke Meyers" <> wrote in message
    > news:...
    > > Cy Edmunds wrote:
    > >> "Krivenok Dmitry" <> wrote in message
    > >> All elements of a container must be of the same type. If it is a pointer
    > >> or
    > >> smart pointer to a common base class we have dynamic polymorphism. Static
    > >> polymorphism can be accomplished using a flag to determine the actual
    > >> type:
    > >>
    > >> struct clumsy
    > >> {
    > >> int flag;
    > >> union (...} other_stuff;
    > >> };

    > >
    > > Uh, I'm pretty sure this is not what most people mean by "static
    > > polymorphism." How did you come to associate the term with this ugly
    > > scheme?
    > >
    > > The "static"/"dynamic" distinction wrt polymorphism, as with e.g.
    > > typing, refers to compile-time vs. run-time. With static polymorphism,
    > > the actual type of the object is known at compile-time. The usual
    > > (only?) mechanism in C++ for this is templates.
    > >
    > > Luke
    > >

    >
    > The original poster asked about heterogeneous containers. How would you do
    > that with templates?
    >

    Check out the following example code:
    http://code.axter.com/HeterogeneousContainer1.cpp
    http://code.axter.com/HeterogeneousContainer2.cpp
    http://code.axter.com/HeterogeneousContainer3.cpp

    Each of the above files have different levels of complexity for
    creating a heterogeneous container.
    The basic idea is to create a wrapper class that acts like an interface
    to the different types.
    Although the types don't have to derive from the same object, they do
    have to have a common method or common data to access.

    ----------------------------------------------------------------------------------------
    David Maisonave
    http://axter.com

    Author of Axter's policy based smart pointers
    (http://axter.com/smartptr)
    Top ten member of C++ Expert Exchange:
    http://www.experts-exchange.com/Cplusplus
    ----------------------------------------------------------------------------------------
     
    Axter, May 31, 2006
    #10
  11. Krivenok Dmitry wrote:
    > Perhaps the most important feature of dynamic polymorphism is
    > ability to handle heterogeneous collections of objects.
    > ("C++ Templates: The Complete Guide" by David Vandevoorde
    > and Nicolai M. Josuttis. Chapter 14.)
    >
    > How to implement analogue of this technique via static polymorphism?
    > Perhaps there is special design pattern for this purpose...



    #include <iostream>
    #include <utility>

    using namespace std;
    class Nil {};

    template <class H, class T> int length(pair<H,T> x) {
    return 1 + length(x.second);
    }
    int length(Nil x) { return 0; }

    int main(int argc, char* argv[])
    {
    cout << length( make_pair(1,
    make_pair(2.0,
    make_pair((int[]){9,8,7},
    make_pair("a string",
    make_pair(true,Nil())))))) << endl;

    return 0;
    }
     
    Greg Buchholz, May 31, 2006
    #11
  12. Krivenok Dmitry

    Cy Edmunds Guest

    "Axter" <> wrote in message
    news:...
    >
    > Cy Edmunds wrote:
    >> "Luke Meyers" <> wrote in message
    >> news:...
    >> > Cy Edmunds wrote:
    >> >> "Krivenok Dmitry" <> wrote in message
    >> >> All elements of a container must be of the same type. If it is a
    >> >> pointer
    >> >> or
    >> >> smart pointer to a common base class we have dynamic polymorphism.
    >> >> Static
    >> >> polymorphism can be accomplished using a flag to determine the actual
    >> >> type:
    >> >>
    >> >> struct clumsy
    >> >> {
    >> >> int flag;
    >> >> union (...} other_stuff;
    >> >> };
    >> >
    >> > Uh, I'm pretty sure this is not what most people mean by "static
    >> > polymorphism." How did you come to associate the term with this ugly
    >> > scheme?
    >> >
    >> > The "static"/"dynamic" distinction wrt polymorphism, as with e.g.
    >> > typing, refers to compile-time vs. run-time. With static polymorphism,
    >> > the actual type of the object is known at compile-time. The usual
    >> > (only?) mechanism in C++ for this is templates.
    >> >
    >> > Luke
    >> >

    >>
    >> The original poster asked about heterogeneous containers. How would you
    >> do
    >> that with templates?
    >>

    > Check out the following example code:
    > http://code.axter.com/HeterogeneousContainer1.cpp
    > http://code.axter.com/HeterogeneousContainer2.cpp
    > http://code.axter.com/HeterogeneousContainer3.cpp
    >
    > Each of the above files have different levels of complexity for
    > creating a heterogeneous container.
    > The basic idea is to create a wrapper class that acts like an interface
    > to the different types.
    > Although the types don't have to derive from the same object, they do
    > have to have a common method or common data to access.
    >
    > ----------------------------------------------------------------------------------------
    > David Maisonave
    > http://axter.com
    >
    > Author of Axter's policy based smart pointers
    > (http://axter.com/smartptr)
    > Top ten member of C++ Expert Exchange:
    > http://www.experts-exchange.com/Cplusplus
    > ----------------------------------------------------------------------------------------
    >


    These are all based on dynamic polymorphism:
    class Coins
    {
    public:
    virtual int GetValue()=0;
    };

    Any smart pointer can function as a template based wrapper for a polymorphic
    type.Cy
     
    Cy Edmunds, Jun 1, 2006
    #12
  13. Krivenok Dmitry

    Cy Edmunds Guest

    "Greg Buchholz" <> wrote in message
    news:...
    > Krivenok Dmitry wrote:
    >> Perhaps the most important feature of dynamic polymorphism is
    >> ability to handle heterogeneous collections of objects.
    >> ("C++ Templates: The Complete Guide" by David Vandevoorde
    >> and Nicolai M. Josuttis. Chapter 14.)
    >>
    >> How to implement analogue of this technique via static polymorphism?
    >> Perhaps there is special design pattern for this purpose...

    >
    >
    > #include <iostream>
    > #include <utility>
    >
    > using namespace std;
    > class Nil {};
    >
    > template <class H, class T> int length(pair<H,T> x) {
    > return 1 + length(x.second);
    > }
    > int length(Nil x) { return 0; }
    >
    > int main(int argc, char* argv[])
    > {
    > cout << length( make_pair(1,
    > make_pair(2.0,
    > make_pair((int[]){9,8,7},
    > make_pair("a string",
    > make_pair(true,Nil())))))) << endl;
    >
    > return 0;
    > }
    >


    Very cool! Done any Lisp programming? hehe

    Cy
     
    Cy Edmunds, Jun 1, 2006
    #13
  14. Krivenok Dmitry

    Axter Guest

    Cy Edmunds wrote:
    > "Axter" <> wrote in message
    > news:...
    > >
    > > Cy Edmunds wrote:
    > >> "Luke Meyers" <> wrote in message
    > >> news:...
    > >> > Cy Edmunds wrote:
    > >> >> "Krivenok Dmitry" <> wrote in message
    > >> >> All elements of a container must be of the same type. If it is a
    > >> >> pointer
    > >> >> or
    > >> >> smart pointer to a common base class we have dynamic polymorphism.
    > >> >> Static
    > >> >> polymorphism can be accomplished using a flag to determine the actual
    > >> >> type:
    > >> >>
    > >> >> struct clumsy
    > >> >> {
    > >> >> int flag;
    > >> >> union (...} other_stuff;
    > >> >> };
    > >> >
    > >> > Uh, I'm pretty sure this is not what most people mean by "static
    > >> > polymorphism." How did you come to associate the term with this ugly
    > >> > scheme?
    > >> >
    > >> > The "static"/"dynamic" distinction wrt polymorphism, as with e.g.
    > >> > typing, refers to compile-time vs. run-time. With static polymorphism,
    > >> > the actual type of the object is known at compile-time. The usual
    > >> > (only?) mechanism in C++ for this is templates.
    > >> >
    > >> > Luke
    > >> >
    > >>
    > >> The original poster asked about heterogeneous containers. How would you
    > >> do
    > >> that with templates?
    > >>

    > > Check out the following example code:
    > > http://code.axter.com/HeterogeneousContainer1.cpp
    > > http://code.axter.com/HeterogeneousContainer2.cpp
    > > http://code.axter.com/HeterogeneousContainer3.cpp
    > >
    > > Each of the above files have different levels of complexity for
    > > creating a heterogeneous container.
    > > The basic idea is to create a wrapper class that acts like an interface
    > > to the different types.
    > > Although the types don't have to derive from the same object, they do
    > > have to have a common method or common data to access.
    > >
    > > ----------------------------------------------------------------------------------------
    > > David Maisonave
    > > http://axter.com
    > >
    > > Author of Axter's policy based smart pointers
    > > (http://axter.com/smartptr)
    > > Top ten member of C++ Expert Exchange:
    > > http://www.experts-exchange.com/Cplusplus
    > > ----------------------------------------------------------------------------------------
    > >

    >
    > These are all based on dynamic polymorphism:
    > class Coins
    > {
    > public:
    > virtual int GetValue()=0;
    > };
    >
    > Any smart pointer can function as a template based wrapper for a polymorphic
    > type.Cy


    The interface is based on dynamic polymorphism, but the target type is
    static polymorphism.
    The target types (Penny, Dime, ....) are not derived from any class,
    and Coins is just an interface to the static type.
    This method mixes both dynamic polymorphism an static polymorphism to
    get a heterogeneous container.

    And, yes you could use a smart pointer to do this with an interface
    class like Coins and the static holder class like TargetClassHolder.
    std::vector<smart_ptr<Coins> > heterogeneousContainer;

    heterogeneousContainer.push_back(TargetClassHolder<Nickel>);

    That would work too.
     
    Axter, Jun 1, 2006
    #14
    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. shablool
    Replies:
    5
    Views:
    484
    mlimber
    Oct 13, 2005
  2. rwf_20
    Replies:
    15
    Views:
    856
    mlimber
    Nov 17, 2005
  3. Replies:
    8
    Views:
    595
  4. crjjrc
    Replies:
    8
    Views:
    427
    James Kanze
    Apr 5, 2007
  5. newbie
    Replies:
    6
    Views:
    405
Loading...

Share This Page