MPL to get rid of cumbersome switch

Hi;
The program belows compiles and works but I'd like to simplify it, maybe
using MPL. I spent some fascinating time educating myself on MPL, reading
C++ Template Metaprogramming, but I am still at sea... to say the least.
Basically the Functor contains a switch statement that is not convenient
especially as the number of T classes will increase dramatically.
Many thanks for any help on that
JCR
#include <iostream>
#include <vector>
#include ::type);
// but it does not compile and MinGW returns:
// error: i cannot appear in a constant expression
// error: template argument 2 is invalid.
}
};
int main (int argc, char ** argv)
{
std::vector<int> runtimeVec;
runtimeVec.push_back(0);
runtimeVec.push_back(1);
runtimeVec.push_back(0);
std::for_each(runtimeVec.begin(), runtimeVec.end(), Functor());
std::cout << vec.size() << std::endl;
return 0;
}

On Thu, 16 Mar 2006, John Christopher wrote:
void operator()(const int& i) { switch(i) { case 0: vec.push_back(new T0); break; case 1: vec.push_back(new T1); break; } // I'd like to simplify the above swtich statement by writing something like: vec.push_back(new boost::mpl::at
::type); // but it does not compile and MinGW returns: // error: i cannot appear in a constant expression // error: template argument 2 is invalid. }
Of course it doesn't compile, because non-type template arguments must be constants known at compile time. However here, the parameter i isn't, and thus cannot be used as a template argument. It would seem like you are stuck with a switch, unless you create something like an array of generating function, e.g.: template < typename T > Tbase* genT() { return new T ; } typedef Tbase* (* genT_type)() ; genT_type generators[] = { & genT< T0 > , & genT< T1 > } ; //... void operator () ( const int i ) { vec.push_back( generators[ i ]() ) ; } It won't be as efficient as the switch though because of the function call through a function pointer. -- François Duranleau LIGUM, Université de Montréal "A person's truth is so simple that most ignore it to concentrate on what they think are deeper truths." - from _Neon Genesis Evangelion_

François Duranleau
On Thu, 16 Mar 2006, John Christopher wrote:
void operator()(const int& i) { switch(i) { case 0: vec.push_back(new T0); break; case 1: vec.push_back(new T1); break; } // I'd like to simplify the above swtich statement by writing something like: vec.push_back(new boost::mpl::at
::type); // but it does not compile and MinGW returns: // error: i cannot appear in a constant expression // error: template argument 2 is invalid. }Of course it doesn't compile, because non-type template arguments must be constants known at compile time. However here, the parameter i isn't, and thus cannot be used as a template argument. It would seem like you are stuck with a switch, unless you create something like an array of generating function, e.g.:
template < typename T > Tbase* genT() { return new T ; }
typedef Tbase* (* genT_type)() ; genT_type generators[] = { & genT< T0 > , & genT< T1 > } ;
//... void operator () ( const int i ) { vec.push_back( generators[ i ]() ) ; }
It won't be as efficient as the switch though because of the function call through a function pointer.
Chapter 11 of "C++ Template Metaprogramming" shows how to generate the equivalent of a switch statement using the MPL. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Thu, 16 Mar 2006, David Abrahams wrote:
Chapter 11 of "C++ Template Metaprogramming" shows how to generate the equivalent of a switch statement using the MPL.
I will need to save up some money to get that book. -- François Duranleau LIGUM, Université de Montréal "Conflict may erupt at any time and any place. War is the destiny of which humanity can never wash its hands." - Emperor Dornkirk, in _The Vision of Escaflowne_

Hello,
Still reading... Chapter 11 is still a few pages away...
Any way, I rewrote the program and I have something much simpler.
The vector of types has not changed:
typedef boost::mpl::vector
::type); break; case 1: vec.push_back(new boost::mpl::at
::type); break; case 2: vec.push_back(new boost::mpl::at ::type); break; case 3: vec.push_back(new boost::mpl::at ::type); break; } } }; struct Display { void operator() (Tbase* p) { p->display(); } }; struct Clean { void operator() (Tbase* p) { delete p; } }; int main (int argc, char ** argv) { std::vector<int> runtimeVec; runtimeVec.push_back(3); runtimeVec.push_back(0); runtimeVec.push_back(0); std::for_each(runtimeVec.begin(), runtimeVec.end(), Functor()); std::cout << vec.size() << std::endl; std::for_each(vec.begin(), vec.end(), Display()); std::for_each(vec.begin(), vec.end(), Clean()); return 0; }
"François Duranleau"
Chapter 11 of "C++ Template Metaprogramming" shows how to generate the equivalent of a switch statement using the MPL.
I will need to save up some money to get that book. -- François Duranleau LIGUM, Université de Montréal "Conflict may erupt at any time and any place. War is the destiny of which humanity can never wash its hands." - Emperor Dornkirk, in _The Vision of Escaflowne_ --------------------------------------------------------------------------------
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

John Christopher wrote:
Hello, Still reading... Chapter 11 is still a few pages away... Any way, I rewrote the program and I have something much simpler. The vector of types has not changed: typedef boost::mpl::vector
TTypes; but the Functor has a new switch statement that is much easier to maintain. The nnumber of cases in the switch must be the number of elements in the vector of types... Adding new cases is no big deal anyway. switch(i) { case 0: vec.push_back(new boost::mpl::at >::type); break; case 1: vec.push_back(new boost::mpl::at >::type); break; ....
Given its prepetitive nature you could use boost preprocessor library to generate this switch... -delfin

Given its prepetitive nature you could use boost preprocessor library to generate this switch...
::type); \ break; BOOST_PP_REPEAT(NUMBER_CASES, CASES, ~); }
That's a good idea.
I could define
#define NUMBER_CASES 4
and the switch would become something like that:
switch(i)
{
#define CASES(z, n, text)
\
case n:
\
vec.push_back(new boost::mpl::at
John Christopher wrote:
Hello, Still reading... Chapter 11 is still a few pages away... Any way, I rewrote the program and I have something much simpler. The vector of types has not changed: typedef boost::mpl::vector
TTypes; but the Functor has a new switch statement that is much easier to maintain. The nnumber of cases in the switch must be the number of elements in the vector of types... Adding new cases is no big deal anyway. switch(i) { case 0: vec.push_back(new boost::mpl::at >::type); break; case 1: vec.push_back(new boost::mpl::at >::type); break; .... Given its prepetitive nature you could use boost preprocessor library to generate this switch...
-delfin

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of John Christopher Sent: Saturday, March 18, 2006 8:26 AM To: boost-users@lists.boost.org Subject: Re: [Boost-users] MPL to get rid of cumbersome switch
Given its prepetitive nature you could use boost preprocessor library to generate this switch...
That's a good idea. I could define #define NUMBER_CASES 4 and the switch would become something like that: switch(i) { #define CASES(z, n, text) \ case n: \ vec.push_back(new boost::mpl::at
::type); \ break; BOOST_PP_REPEAT(NUMBER_CASES, CASES, ~); } this compiles and works fine, but, since the number of cases in the switch must equal the size of the vector of type, I'd rather write something like: #define NUMBER_CASES boost::mpl::size<TTypes>::value but this does not compile and I am getting the error
Yeah, that won't work because the preprocessor cannot evaluate 'boost::mpl::size<TTypes>::value'. If you're going to use the preprocessor for this, you need to store the types in a preprocessor data structure, not an mpl::vector. (Note, BTW, than an MPL vector can be trivial created from a preprocessor data structure.) Regards, Paul Mensonides

"Paul Mensonides"
Yeah, that won't work because the preprocessor cannot evaluate 'boost::mpl::size<TTypes>::value'. If you're going to use the preprocessor for this, you need to store the types in a preprocessor data structure, not an mpl::vector. (Note, BTW, than an MPL vector can be trivial created from a preprocessor data structure.)
If you don't want to do that, you'll have to resort to generating a chained "if" set of inline function calls containing "if" statements. Unless there are many cases, that may be as fast as a case statement. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"Paul Mensonides" wrote:
Yeah, that won't work because the preprocessor cannot evaluate 'boost::mpl::size<TTypes>::value'. If you're going to use the preprocessor for this, you need to store the types in a preprocessor data structure, not an mpl::vector. (Note, BTW, than an MPL vector can be trivial created from a preprocessor data structure.)
Thanks for the idea; the program compiles and works fine; it is easy to
maintain since I have only the preprocessor data structure to keep updated
when I add T classes. I am getting some type checking for instance if I add
to the TYPES preprocessor data structure a type that does not exist. MPL and
preprocesor library are great tools!
JCR
#define MY_TYPES (T0) (T1) (T2) (T3) (T4)
typedef boost::mpl::vector ::type); \
break;
BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(MY_TYPES), CASES, ~);
}
}
}; "Paul Mensonides" -----Original Message-----
From: boost-users-bounces@lists.boost.org
[mailto:boost-users-bounces@lists.boost.org] On Behalf Of
John Christopher
Sent: Saturday, March 18, 2006 8:26 AM
To: boost-users@lists.boost.org
Subject: Re: [Boost-users] MPL to get rid of cumbersome switch Given its prepetitive nature you could use boost
preprocessor library
to generate this switch... That's a good idea.
I could define
#define NUMBER_CASES 4
and the switch would become something like that:
switch(i)
{
#define CASES(z, n, text)
\
case n:
\
vec.push_back(new boost::mpl::at but this does not compile and I am getting the error Yeah, that won't work because the preprocessor cannot evaluate
'boost::mpl::size<TTypes>::value'. If you're going to use the
preprocessor for
this, you need to store the types in a preprocessor data structure, not an
mpl::vector. (Note, BTW, than an MPL vector can be trivial created from a
preprocessor data structure.) Regards,
Paul Mensonides
participants (5)
-
David Abrahams
-
Delfin Rojas
-
François Duranleau
-
John Christopher
-
Paul Mensonides