Code bloating when choosing template argument based on cmdline input

P

PengYu.UT

Hi,

I have two questions.

1. Are there any good way to generalize the code for switch statement
with any number of cases?

2. Suppose test() is a very big function, and there are many cases in
the switch statement. The binary code could be huge. Are there any
method to deal with this problem.

Note: I have to path N as a template argument because the compiler can
optimize test much better than if I pass N as a function argument.

Thanks,
Peng

#include <iostream>
#include <cstdlib>

template <int N>
void test() {
std::cout << N << std::endl;
//Can be a very long function.
}

int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
switch(n) {
case 0: test<0>(); break;
case 1: test<1>(); break;
case 2: test<2>(); break;
case 3: test<3>(); break;
case 4: test<4>(); break;
case 5: test<5>(); break;// Can be much more than 5 cases
default:
std::cout << "not found" << std::endl;
}
}
 
T

Taran

Hi,

I have two questions.

1. Are there any good way to generalize the code for switch statement
with any number of cases?

There are good ways and 'good' differs from case to case. Figure out
the commonality and put them in a function. The variations in terms of
inputs to be operated on can be passed as arguments.
2. Suppose test() is a very big function, and there are many cases in
the switch statement. The binary code could be huge. Are there any
method to deal with this problem.

Yes many instantiations of a template can lead to code bloat, the
object code will be huge. Find an alternate way.
example, you have a queue implementation where the element type is a
template param, so long as you do not have many instantiations like
200 odd, its fine. But if you have more than that then change your
design.
Note: I have to path N as a template argument because the compiler can
optimize test much better than if I pass N as a function argument.

Thanks,
Peng

#include <iostream>
#include <cstdlib>

template <int N>
void test() {
std::cout << N << std::endl;
//Can be a very long function.

}

int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
switch(n) {
case 0: test<0>(); break;
case 1: test<1>(); break;
case 2: test<2>(); break;
case 3: test<3>(); break;
case 4: test<4>(); break;
case 5: test<5>(); break;// Can be much more than 5 cases
default:
std::cout << "not found" << std::endl;
}

}

Consider this:


#include <iostream>
#include <cstdlib>


void test(int N) {
std::cout << N << std::endl;
//Can be a very long function.
// I guess you either do not need N here or will be doing some
operations on N.
//
}

int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
switch(n) {
case 0: test(0); break;
case 1: test(1); break;
case 2: test(2); break;
case 3: test(3); break;
case 4: test(4); break;
case 5: test(5); break;// Can be much more than 5 cases
default:
std::cout << "not found" << std::endl;
}
}

HTH
 
P

PengYu.UT

I have two questions.
1. Are there any good way to generalize the code for switch statement
with any number of cases?

There are good ways and 'good' differs from case to case. Figure out
the commonality and put them in a function. The variations in terms of
inputs to be operated on can be passed as arguments.
2. Suppose test() is a very big function, and there are many cases in
the switch statement. The binary code could be huge. Are there any
method to deal with this problem.

Yes many instantiations of a template can lead to code bloat, the
object code will be huge. Find an alternate way.
example, you have a queue implementation where the element type is a
template param, so long as you do not have many instantiations like
200 odd, its fine. But if you have more than that then change your
design.


Note: I have to path N as a template argument because the compiler can
optimize test much better than if I pass N as a function argument.

#include <iostream>
#include <cstdlib>
template <int N>
void test() {
std::cout << N << std::endl;
//Can be a very long function.

int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
switch(n) {
case 0: test<0>(); break;
case 1: test<1>(); break;
case 2: test<2>(); break;
case 3: test<3>(); break;
case 4: test<4>(); break;
case 5: test<5>(); break;// Can be much more than 5 cases
default:
std::cout << "not found" << std::endl;
}

Consider this:

#include <iostream>
#include <cstdlib>

void test(int N) {
std::cout << N << std::endl;
//Can be a very long function.
// I guess you either do not need N here or will be doing some
operations on N.
//
}

In fact, I used this approach. But it is not as efficient as the
templated version of "test" function. The runtime difference can be a
few times.

It seems there is no good solution to this problem. I have to use the
templated version of "test", which is not flexible to accept arbitrary
arguments.
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
switch(n) {
case 0: test(0); break;
case 1: test(1); break;
case 2: test(2); break;
case 3: test(3); break;
case 4: test(4); break;
case 5: test(5); break;// Can be much more than 5 cases
default:
std::cout << "not found" << std::endl;
}
}

HTH
 
Z

Zeppe

Hi,

I have two questions.

1. Are there any good way to generalize the code for switch statement
with any number of cases?

no. You have to state explicitly the parameters in the template version,
because for each different template parameter set a different class and
different code will be instantiated.
2. Suppose test() is a very big function, and there are many cases in
the switch statement. The binary code could be huge. Are there any
method to deal with this problem.

No. A different code will be generated for each class at compile time.
Note: I have to path N as a template argument because the compiler can
optimize test much better than if I pass N as a function argument.

well, of course, because a lot of choices can be done at compile-time.
Remember, however, that this approach limits by far the flexibility of
the system. The major drawback is that you have to fix all the
parameters at compile time. Otherwise, optimise the code in another way,
usually this can lead to very good results as well.
Thanks,
Peng

#include <iostream>
#include <cstdlib>

template <int N>
void test() {
std::cout << N << std::endl;
//Can be a very long function.
}

In this example, the performance difference should be negligible. Are
you sure that your optimisations depend on the template and you are not
omitting some important optimisation consideration that is not related
with the templates?

Regards,

Zeppe
 
K

Kai-Uwe Bux

Hi,

I have two questions.

1. Are there any good way to generalize the code for switch statement
with any number of cases?

Good? Not really. The template has to be instantiated for all values that
you need. You can ask the compiler to do that, but the compiler will not be
happy:


#include <cstddef>
#include <iostream>

template <int N>
void test() {
std::cout << N << std::endl;
//Can be a very long function.
}

template < typename ArithmeticType,
ArithmeticType first, ArithmeticType last >
void
bin_search ( ArithmeticType val ) {
if ( first == last ) {
test<first>();
return;
}
if ( ( first + ( last-first )/2 ) < val ) {
bin_search< ArithmeticType, ( last - ( last-first )/2), last >( val );
} else {
bin_search< ArithmeticType, first, ( first + ( last-first )/2) >( val );
}
}

int main(int argc, char *argv[]) {
unsigned char n = atoi(argv[1]);
bin_search<unsigned char, 0,-1>( n );
}

Expect your compiler to get mad if you try this for unsigned long instead of
unsigned char.

2. Suppose test() is a very big function, and there are many cases in
the switch statement. The binary code could be huge. Are there any
method to deal with this problem.

Yes: don't make N a template parameter.
Note: I have to path N as a template argument because the compiler can
optimize test much better than if I pass N as a function argument.

Oh well, never mind.


Best

Kai-Uwe Bux
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top