By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,806 Members | 1,089 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,806 IT Pros & Developers. It's quick & easy.

How to avoid runtime switch/case code based on data type?

P: n/a
Hi Group, I've got a problem I couldn't find a good solution. I am
working with scientific data files in netCDF format. One of the
properties of netCDF data is that the actual type of data is only known
at run time. Therefore a lot of template based trick isn't too useful.
Considering

datafile
float x(3) 3.5, 2.5, 8.9
double y(3) 2.7, -2.3, 1.2
int z(3) 5, 2, 3

Suppose in my code, I need to write a summation function and return the
result, I could do

template <class T>
T sum(T * data, size_t n);

This is all good and dandy, but in the calling subroutine I am stuck
because at compile I have no priori knowledge of actual data type
contained in the data file, thus I must rely on switch/case code based
on what may be contained in the data file during run time. Consider:

void sum_caller(){
mytype type = datafile.getline(i).type
switch(type){
case float_type:
float ret = sum(datafile.getline(i).data);
do_something(ret);
case double_type:
float ret = sum(datafile.getline(i).data);
...
....
}

I cannot declare 'template <class T> void sum_caller();' because only
within sum_caller, the type information is available. (you could argue
I can declare sum_caller template based, but that's not the point. At
some point, the type information becomes available and appropriate
action can be taken). Is there a design pattern or implementation
strategy that can help me with this dilemma and thus avoid switch/case
based code altogether? Thanks!

Mar 3 '06 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Fei Liu wrote:
Hi Group, I've got a problem I couldn't find a good solution. I am
working with scientific data files in netCDF format. One of the
properties of netCDF data is that the actual type of data is only known
at run time. Therefore a lot of template based trick isn't too useful.
Considering

datafile
float x(3) 3.5, 2.5, 8.9
double y(3) 2.7, -2.3, 1.2
int z(3) 5, 2, 3

Suppose in my code, I need to write a summation function and return the
result, I could do

template <class T>
T sum(T * data, size_t n);

This is all good and dandy, but in the calling subroutine I am stuck
because at compile I have no priori knowledge of actual data type
contained in the data file, thus I must rely on switch/case code based
on what may be contained in the data file during run time. Consider:

void sum_caller(){
mytype type = datafile.getline(i).type
switch(type){
case float_type:
float ret = sum(datafile.getline(i).data);
do_something(ret);
case double_type:
float ret = sum(datafile.getline(i).data);
...
...
}

I cannot declare 'template <class T> void sum_caller();' because only
within sum_caller, the type information is available. (you could argue
I can declare sum_caller template based, but that's not the point. At
some point, the type information becomes available and appropriate
action can be taken). Is there a design pattern or implementation
strategy that can help me with this dilemma and thus avoid switch/case
based code altogether? Thanks!


Check out chapter 8 of _Modern C++ Design_ by Andrei Alexandrescu. A
Loki factory is intended to fill just such a gap and will likely do
what you need (well, with a little effort on your part). You can get
the latest source code for it from

http://sourceforge.net/projects/loki-lib/

Cheers! --M

Mar 3 '06 #2

P: n/a
On 2006-03-03, Fei Liu <fe*****@gmail.com> wrote:
Hi Group, I've got a problem I couldn't find a good solution. I am
working with scientific data files in netCDF format. One of the
properties of netCDF data is that the actual type of data is only
known at run time. Therefore a lot of template based trick isn't too
useful. Considering

datafile
float x(3) 3.5, 2.5, 8.9
double y(3) 2.7, -2.3, 1.2
int z(3) 5, 2, 3


It looks like you need a parser, rather, and it's already been
written. A visit to the CVS repository for NCO seems like the best
place to start.

--
Neil Cerutti
I pulled into a lay-by with smoke coming from under the bonnet.
I realized the car was on fire so took my dog and smothered it
with a blanket. --Insurance Claim Blooper
Mar 3 '06 #3

P: n/a

Neil Cerutti wrote:
On 2006-03-03, Fei Liu <fe*****@gmail.com> wrote:
Hi Group, I've got a problem I couldn't find a good solution. I am
working with scientific data files in netCDF format. One of the
properties of netCDF data is that the actual type of data is only
known at run time. Therefore a lot of template based trick isn't too
useful. Considering

datafile
float x(3) 3.5, 2.5, 8.9
double y(3) 2.7, -2.3, 1.2
int z(3) 5, 2, 3


It looks like you need a parser, rather, and it's already been
written. A visit to the CVS repository for NCO seems like the best
place to start.

--
Neil Cerutti
I pulled into a lay-by with smoke coming from under the bonnet.
I realized the car was on fire so took my dog and smothered it
with a blanket. --Insurance Claim Blooper


How does a parser solve my problem?

Mar 3 '06 #4

P: n/a
Fei Liu wrote:
Hi Group, I've got a problem I couldn't find a good solution. I am
working with scientific data files in netCDF format. One of the
properties of netCDF data is that the actual type of data is only
known at run time. Therefore a lot of template based trick isn't too
useful. Considering

datafile
float x(3) 3.5, 2.5, 8.9
double y(3) 2.7, -2.3, 1.2
int z(3) 5, 2, 3


mlimber's loki suggestion might work.

In general, faced with A> a boundary between the outside world and a
program, and B> a switch based on type codes, you need polymorphism. Create
a Class Factory that converts each typed object into a wrapper object with
virtual methods. Return a reference to an abstract base class declaring
those methods, and call them. Each one will convert the data in its own
special way, and the calling code can be very clean.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 3 '06 #5

P: n/a
In general, faced with A> a boundary between the outside world and a
program, and B> a switch based on type codes, you need polymorphism. Create
a Class Factory that converts each typed object into a wrapper object with
virtual methods. Return a reference to an abstract base class declaring
those methods, and call them. Each one will convert the data in its own
special way, and the calling code can be very clean.


What would be the right 'search term' - if you will for this. I'd like
to look this up on the web (find an example or two), since I tend to go
the switch route on a continuum. In my heart of hearts I know there's
a polymorphic solution.

Mar 3 '06 #6

P: n/a
In general, faced with A> a boundary between the outside world and a
program, and B> a switch based on type codes, you need polymorphism. Create
a Class Factory that converts each typed object into a wrapper object with
virtual methods. Return a reference to an abstract base class declaring
those methods, and call them. Each one will convert the data in its own
special way, and the calling code can be very clean.


What would be the right 'search term' - if you will for this? I'd like
to look this up on the web (find an example or two), since I tend to go
the switch route on a continuum. In my heart of hearts I know there's
a polymorphic solution.

Mar 3 '06 #7

P: n/a
ma740988 wrote:
What would be the right 'search term' - if you will for this?


http://www.google.com/search?q=factory+pattern

http://www.google.com/search?q=repla...h+polymorphism

Some consider that last one the heart of OOP.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 3 '06 #8

P: n/a
In article <11*********************@i40g2000cwc.googlegroups. com>,
"Fei Liu" <fe*****@gmail.com> wrote:
Hi Group, I've got a problem I couldn't find a good solution. I am
working with scientific data files in netCDF format. One of the
properties of netCDF data is that the actual type of data is only known
at run time. Therefore a lot of template based trick isn't too useful.
Considering

datafile
float x(3) 3.5, 2.5, 8.9
double y(3) 2.7, -2.3, 1.2
int z(3) 5, 2, 3

Suppose in my code, I need to write a summation function and return the
result, I could do

template <class T>
T sum(T * data, size_t n);

This is all good and dandy, but in the calling subroutine I am stuck
because at compile I have no priori knowledge of actual data type
contained in the data file, thus I must rely on switch/case code based
on what may be contained in the data file during run time. Consider:

void sum_caller(){
mytype type = datafile.getline(i).type
switch(type){
case float_type:
float ret = sum(datafile.getline(i).data);
do_something(ret);
case double_type:
float ret = sum(datafile.getline(i).data);
...
...
}

I cannot declare 'template <class T> void sum_caller();' because only
within sum_caller, the type information is available. (you could argue
I can declare sum_caller template based, but that's not the point. At
some point, the type information becomes available and appropriate
action can be taken). Is there a design pattern or implementation
strategy that can help me with this dilemma and thus avoid switch/case
based code altogether? Thanks!


Switch statements are not evil, what is evil is having multiple switch
statements in your code, all switching based on the same type
information. If you have that, then create an ABC, use one switch to
create the derived object and don't worry about it. KISS
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Mar 3 '06 #9

P: n/a
Howdy Daniel,
Switch statements are not evil, what is evil is having multiple switch
statements in your code, all switching based on the same type
information. If you have that, then create an ABC, use one switch to
create the derived object and don't worry about it. KISS

"KISS". Indeed. I think though I mirror the multiple switch statement
based on same type information you alluded to. So now consider an
enumerated type with a list of algorithms'.

enum algorithm_type { BEM, IFFT, FFT, INVALID = -1 };

This type forms is part of a composite type such that:
struct algorithm_details {
// stuff
// later
algorithm_type pcp_type;
};

Upon receipt of the header (+ data) from an external source, I do:
switch ( algorithm_type )
{
case BEM : // perform field compuations on the data using
Maxwells equations.
break;
case IFFT: // do an inverse FFT
break;
case FFT: // do an FFT
};
etc.

Something tells me that a more viable solution would be as follows:
class algorithm {
public: algorithm() {}
virtual void do_bem( /*whatever */ ) = 0;
// and so on.
};

// later
class foo : public algorithm {
public:
foo () : algorithm() {}
void do_bem( /* whatever */ ) {}
~virtual foo { void cleanup(); }
void cleanup () { /* what goes up must come down - tear down */ }
};

Ultimately what it amounts to is the mathematics ( matrix mess ) is so
involved that your 'case statements ' becomes large. Of ocurse the
alternative is to call member functions based on the type. In any
event, I think you see where I'm going .. Your thoughts.

Mar 4 '06 #10

P: n/a
In article <11**********************@j33g2000cwa.googlegroups .com>,
"ma740988" <ma******@gmail.com> wrote:
Howdy Daniel,
Switch statements are not evil, what is evil is having multiple switch
statements in your code, all switching based on the same type
information. If you have that, then create an ABC, use one switch to
create the derived object and don't worry about it. KISS

"KISS". Indeed. I think though I mirror the multiple switch statement
based on same type information you alluded to. So now consider an
enumerated type with a list of algorithms'.

enum algorithm_type { BEM, IFFT, FFT, INVALID = -1 };

This type forms is part of a composite type such that:
struct algorithm_details {
// stuff
// later
algorithm_type pcp_type;
};

Upon receipt of the header (+ data) from an external source, I do:
switch ( algorithm_type )
{
case BEM : // perform field compuations on the data using
Maxwells equations.
break;
case IFFT: // do an inverse FFT
break;
case FFT: // do an FFT
};
etc.

Something tells me that a more viable solution would be as follows:
class algorithm {
public: algorithm() {}
virtual void do_bem( /*whatever */ ) = 0;
// and so on.
};

// later
class foo : public algorithm {
public:
foo () : algorithm() {}
void do_bem( /* whatever */ ) {}
~virtual foo { void cleanup(); }
void cleanup () { /* what goes up must come down - tear down */ }
};

Ultimately what it amounts to is the mathematics ( matrix mess ) is so
involved that your 'case statements ' becomes large. Of ocurse the
alternative is to call member functions based on the type. In any
event, I think you see where I'm going .. Your thoughts.


The problem is, you have the header (+data) from an external source. In
order to use a virtual method on a base class you first need to make an
object of some derived class. The type of object you need to make is
based on the very type your doing the switch on anyway.

In other words, you must do at least one switch on the type (either to
do the calculation or create the object.) It's having more than one
switch on type that could be a problem.
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Mar 4 '06 #11

P: n/a

Daniel T. wrote:
In article <11**********************@j33g2000cwa.googlegroups .com>,
"ma740988" <ma******@gmail.com> wrote:
Howdy Daniel,
Switch statements are not evil, what is evil is having multiple switch
statements in your code, all switching based on the same type
information. If you have that, then create an ABC, use one switch to
create the derived object and don't worry about it. KISS
"KISS". Indeed. I think though I mirror the multiple switch statement
based on same type information you alluded to. So now consider an
enumerated type with a list of algorithms'.

enum algorithm_type { BEM, IFFT, FFT, INVALID = -1 };

This type forms is part of a composite type such that:
struct algorithm_details {
// stuff
// later
algorithm_type pcp_type;
};

Upon receipt of the header (+ data) from an external source, I do:
switch ( algorithm_type )
{
case BEM : // perform field compuations on the data using
Maxwells equations.
break;
case IFFT: // do an inverse FFT
break;
case FFT: // do an FFT
};
etc.

Something tells me that a more viable solution would be as follows:
class algorithm {
public: algorithm() {}
virtual void do_bem( /*whatever */ ) = 0;
// and so on.
};

// later
class foo : public algorithm {
public:
foo () : algorithm() {}
void do_bem( /* whatever */ ) {}
~virtual foo { void cleanup(); }
void cleanup () { /* what goes up must come down - tear down */ }
};

Ultimately what it amounts to is the mathematics ( matrix mess ) is so
involved that your 'case statements ' becomes large. Of ocurse the
alternative is to call member functions based on the type. In any
event, I think you see where I'm going .. Your thoughts.


The problem is, you have the header (+data) from an external source. In
order to use a virtual method on a base class you first need to make an
object of some derived class. The type of object you need to make is
based on the very type your doing the switch on anyway.


This is the gist of the problem. Things are not known at compile time
and variables of proper type can only be declared at run time based on
external information... In other words, you must do at least one switch on the type (either to
do the calculation or create the object.) It's having more than one
switch on type that could be a problem.
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.


Mar 4 '06 #12

P: n/a
>
The problem is, you have the header (+data) from an external source. In
order to use a virtual method on a base class you first need to make an
object of some derived class. The type of object you need to make is
based on the very type your doing the switch on anyway.


This is the gist of the problem. Things are not known at compile time
and variables of proper type can only be declared at run time based on
external information...
In other words, you must do at least one switch on the type (either to
do the calculation or create the object.) It's having more than one
switch on type that could be a problem.

Thanks. By the way Fei, I might have overstepped my bounds there. In
that Daniel wasn't responding to me but for some reason I didn't
realize that until after it's too late.

My apologies.

Mar 5 '06 #13

P: n/a
On 2006-03-03, Fei Liu <fe*****@gmail.com> wrote:

Neil Cerutti wrote:
On 2006-03-03, Fei Liu <fe*****@gmail.com> wrote:
> Hi Group, I've got a problem I couldn't find a good solution. I am
> working with scientific data files in netCDF format. One of the
> properties of netCDF data is that the actual type of data is only
> known at run time. Therefore a lot of template based trick isn't too
> useful. Considering
>
> datafile
> float x(3) 3.5, 2.5, 8.9
> double y(3) 2.7, -2.3, 1.2
> int z(3) 5, 2, 3


It looks like you need a parser, rather, and it's already been
written. A visit to the CVS repository for NCO seems like the best
place to start.

--
Neil Cerutti
I pulled into a lay-by with smoke coming from under the bonnet.
I realized the car was on fire so took my dog and smothered it
with a blanket. --Insurance Claim Blooper


How does a parser solve my problem?


Never mind me. I misunderestimated the problem. Sorry.

--
Neil Cerutti
Women's Luncheon: Each member bring a sandwich. Polly Phillips
will give the medication. --Church Bulletin Blooper
Mar 6 '06 #14

This discussion thread is closed

Replies have been disabled for this discussion.