Dynamic polymorphism vs. Static polymorphism

K

Krivenok Dmitry

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!
 
U

Ulrich Hobelmann

Krivenok said:
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?
 
M

mlimber

Ulrich said:
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
 
A

Alan Johnson

Krivenok said:
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.
 
N

Noah Roberts

mlimber said:
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.
 
M

mlimber

Noah said:
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
 
C

Cy Edmunds

Krivenok Dmitry said:
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
 
L

Luke Meyers

Cy said:
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
 
C

Cy Edmunds

Luke Meyers said:
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
 
A

Axter

Cy said:
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
----------------------------------------------------------------------------------------
 
G

Greg Buchholz

Krivenok said:
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;
}
 
C

Cy Edmunds

Axter said:
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
 
C

Cy Edmunds

Greg Buchholz said:
Krivenok said:
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
 
A

Axter

Cy said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top