473,511 Members | 15,624 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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

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
13 4503
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
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

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

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
>
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
2420
by: Dave | last post by:
Hello all, I am creating a linked list implementation which will be used in a number of contexts. As a result, I am defining its value node as type (void *). I hope to pass something in to its...
9
1437
by: Jon Rea | last post by:
I hav been looking for the last 2 hours on how to do this without much luck. Im going to give a simplifed model of the problem i have. I want a collection class that can holds a series or...
3
19727
by: pgraeve | last post by:
I am a convert from VB to C# so bear with me on this "conversion" question C# switch statement seems to be the closest relative to VB's Select Case. I used VB's Select Case statement liberally. ...
19
3772
by: rdavis7408 | last post by:
Hello, I have four textboxes that the user enters the price per gallon paid at the pump, the mileage per gallon and I would like to then calculate the cost per gallon and use a switch statement to...
12
5755
by: leaf | last post by:
Hi, How to call function at runtime, based on a struct that contains the information for the function call: struct func_to_call { int function_id; // function id to call unsigned int nparams;...
18
4314
by: John Friedland | last post by:
My problem: I need to call (from C code) an arbitrary C library function, but I don't know until runtime what the function name is, how many parameters are required, and what the parameters are. I...
2
6555
by: Angel Of Death | last post by:
I have a method. It takes some XML as a parameter. Depending on the content of the XML it should create a specific object and call a KNOWN method. So: public void PersistXml(string XmlData){} ...
18
3616
by: desktop | last post by:
I have 3 types of objects: bob1, bob2 and bob3. Each object is identified by a unique ID which gets returned by the function getId(). All bobs are descendants from class BaseBob which is an...
9
6108
by: Dhiru1009 | last post by:
Hi guys, I am trying to build a user registration form using PHP and MYSQL but encountring a problem. When I click on submit with empty fields it adds records to database also it doesn't matter...
0
7153
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
1
7093
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5676
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5077
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4743
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3230
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3218
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1583
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
452
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.