[preprocessor] concatenating values to create typedef permutations
Hi, I am trying to use the preprocessor iteration ability to create typedef permutations. I want to do something like use the following set of types TYPE1: char int float TYPE2: char int float double to generate permutations of MyClass<TYPE1,TYPE2> such as typedef MyClass<char,char> Mycc; typedef MyClass<char,int> Myci; typedef MyClass<char,float> Mycf; ... Any help would be greatly appreciated. Thanks, Chris
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Chris Weed
Hi, I am trying to use the preprocessor iteration ability to create typedef permutations.
I want to do something like use the following set of types TYPE1: char int float TYPE2: char int float double
to generate permutations of MyClass<TYPE1,TYPE2> such as
typedef MyClass<char,char> Mycc; typedef MyClass<char,int> Myci; typedef MyClass<char,float> Mycf; ...
Creating the permutations is easy, but you can't automatically extract the first character of an identifier (e.g. 'char' is an identifier to the preprocessor) to generate the "unique" typedef name. The best that you can do is either pass it along as a separate field (what the code below does) or provide a way to obtain it through some kind of type registration. Regards, Paul Mensonides #include <boost/preprocessor/seq/cat.hpp> #include <boost/preprocessor/seq/elem.hpp> #include <boost/preprocessor/seq/enum.hpp> #include <boost/preprocessor/seq/for_each_product.hpp> #include <boost/preprocessor/seq/transform.hpp> #define A(r, product) \ typedef MyClass< \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(B, 1, product)) \ > \ BOOST_PP_SEQ_CAT((My) BOOST_PP_SEQ_TRANSFORM(B, 0, product)); \ /**/ #define B(s, i, elem) BOOST_PP_SEQ_ELEM(i, elem) #define TYPE(alpha, id) ((alpha)(id)) BOOST_PP_SEQ_FOR_EACH_PRODUCT( A, ( TYPE(c, char) TYPE(i, int) TYPE(f, float) ) ( TYPE(c, char) TYPE(i, int) TYPE(f, float) TYPE(d, double) ) ) #undef A #undef B #undef TYPE
Thanks, That is exactly what I need. I don't want to take up too much more of your time, but how would I add template arguments for template template parameters like: typedef MyClassA<float,MyClassB<bool,char>,int> Myfbci; MyClassA and MyClassB don't need to change. Chris
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Chris Weed
Thanks, That is exactly what I need. I don't want to take up too much more of your time, but how would I add template arguments for template template parameters like:
typedef MyClassA<float,MyClassB<bool,char>,int> Myfbci;
MyClassA and MyClassB don't need to change.
I'm not sure what you mean. Do you mean passing 'MyClassB<bool, char>' as one of the elements of the permutated sequences, or do you mean that 'bool' and 'char' are elements of the permutated sequences? (On my way out the door, and I won't be able to reply for about ten hours.) Regards, Paul Mensonides
Sorry for my poor explanation. What I was trying to do was permute the types that weren't MyClassA and MyClassB Such as: typedef MyClassA<float,MyClassB<bool,char>,int> My_fbci; typedef MyClassA<float,MyClassB<bool,char>,float> My_fbcf; typedef MyClassA<char,MyClassB<float,float>,float> My_cfff; typedef MyClassA<float,MyClassB<int,float>,float> My_fiff; ... Thanks for your help, Chris On 6/14/06, Paul Mensonides <pmenso57@comcast.net> wrote:
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Chris Weed
Thanks, That is exactly what I need. I don't want to take up too much more of your time, but how would I add template arguments for template template parameters like:
typedef MyClassA<float,MyClassB<bool,char>,int> Myfbci;
MyClassA and MyClassB don't need to change.
I'm not sure what you mean. Do you mean passing 'MyClassB<bool, char>' as one of the elements of the permutated sequences, or do you mean that 'bool' and 'char' are elements of the permutated sequences?
(On my way out the door, and I won't be able to reply for about ten hours.)
Regards, Paul Mensonides
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Actually, I did get a hacked up version of your code to do this, but it certainly isn't elegant. Here it is: #include <boost/preprocessor/seq/cat.hpp> #include <boost/preprocessor/seq/elem.hpp> #include <boost/preprocessor/seq/enum.hpp> #include <boost/preprocessor/seq/for_each_product.hpp> #include <boost/preprocessor/seq/transform.hpp> #define A(r, product) \ typedef MyClass< \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(B, 1, product)) \
\ BOOST_PP_SEQ_CAT((My_) BOOST_PP_SEQ_TRANSFORM(B, 0, product)); \ /**/ #define B(s, i, elem) BOOST_PP_SEQ_ELEM(i, elem)
#define TYPE(alpha, id) ((alpha)(id)) BOOST_PP_SEQ_FOR_EACH_PRODUCT( A, ( TYPE(c, char) TYPE(i, int) TYPE(f, float) ) ( TYPE(c, MyClassB<char) TYPE(b, MyClassB<bool)) ( TYPE(c, char>) TYPE(i, int>) TYPE(f, float>) TYPE(d, double>) ) ( TYPE(c, char) TYPE(i, int) TYPE(f, float) TYPE(d, double) ) ) #undef A #undef B #undef TYPE Thanks again, Chris On 6/14/06, Chris Weed <chrisweed@gmail.com> wrote:
Sorry for my poor explanation. What I was trying to do was permute the types that weren't MyClassA and MyClassB
Such as: typedef MyClassA<float,MyClassB<bool,char>,int> My_fbci; typedef MyClassA<float,MyClassB<bool,char>,float> My_fbcf; typedef MyClassA<char,MyClassB<float,float>,float> My_cfff; typedef MyClassA<float,MyClassB<int,float>,float> My_fiff; ...
Thanks for your help, Chris
On 6/14/06, Paul Mensonides <pmenso57@comcast.net> wrote:
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Chris Weed
Thanks, That is exactly what I need. I don't want to take up too much more of your time, but how would I add template arguments for template template parameters like:
typedef MyClassA<float,MyClassB<bool,char>,int> Myfbci;
MyClassA and MyClassB don't need to change.
I'm not sure what you mean. Do you mean passing 'MyClassB<bool, char>' as one of the elements of the permutated sequences, or do you mean that 'bool' and 'char' are elements of the permutated sequences?
(On my way out the door, and I won't be able to reply for about ten hours.)
Regards, Paul Mensonides
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Chris Weed Sent: Wednesday, June 14, 2006 6:24 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [preprocessor] concatenating values tocreatetypedefpermutations
Sorry for my poor explanation. What I was trying to do was permute the types that weren't MyClassA and MyClassB
Such as: typedef MyClassA<float,MyClassB<bool,char>,int> My_fbci; typedef MyClassA<float,MyClassB<bool,char>,float> My_fbcf; typedef MyClassA<char,MyClassB<float,float>,float> My_cfff; typedef MyClassA<float,MyClassB<int,float>,float> My_fiff; ...
#define A(r, product) \ typedef MyClass< \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(B, 1, product)) \ > \ BOOST_PP_SEQ_CAT((My) BOOST_PP_SEQ_TRANSFORM(B, 0, product)); \ /**/ #define B(s, i, elem) BOOST_PP_SEQ_ELEM(i, elem) Okay, in this part of the code, the 'product' argument that is passed to 'A' is a sequence containing a particular permutation (e.g. (char)(int)). However, because we're passing the single letters to use in the construction of the typedef name, that sequence is actually, e.g., ((c)(char))((i)(int)). IOW, a sequence where each element is another sequence that contains a letter and a type. The SEQ_TRANSFORMs are just converting that sequence into (char)(int) and (c)(i) respectively so that we can reuse other already-defined library primitives like SEQ_ENUM and SEQ_CAT. Long story short, we have the permutation in 'product', we just need to extract the parts that we need at various locations: #include <boost/preprocessor/seq/cat.hpp> #include <boost/preprocessor/seq/elem.hpp> #include <boost/preprocessor/seq/for_each_product.hpp> #include <boost/preprocessor/seq/transform.hpp> // Here we change A so that it just splits the // permutation sequence into two sequences-- // one containing the types and one containing // the letters--which we just forward to C. // E.g. // // ((c)(char)) ((i)(int)) ((d)(double)) ((f)(float)) // -> (char)(int)(double)(float) // -> (c)(i)(d)(f) // // The first transformation (the types) isn't // strictly necessary, but it makes the syntax // cleaner in C. Without that transformation, // access to the n-th type in the permutation // would be SEQ_ELEM(1, SEQ_ELEM(n, product)). // Pulling the types out into a separate // sequence results in SEQ_ELEM(n, types) // instead. The second transformation is // necessary if we want to use SEQ_CAT to make // the typedef name. #define A(r, product) \ C( \ BOOST_PP_SEQ_TRANSFORM(B, 1, product), \ BOOST_PP_SEQ_TRANSFORM(B, 0, product) \ ) \ /**/ #define B(s, i, elem) BOOST_PP_SEQ_ELEM(i, elem) // Here we just extract the types from the // the 'types' sequence were we want them. // The typedef name is constructed the same as // before. #define C(types, letters) \ typedef MyClassA< \ BOOST_PP_SEQ_ELEM(0, types), \ MyClassB< \ BOOST_PP_SEQ_ELEM(1, types), \ BOOST_PP_SEQ_ELEM(2, types) \ >, \ BOOST_PP_SEQ_ELEM(3, types) \ > BOOST_PP_SEQ_CAT((My_) letters); \ /**/ #define TYPE(alpha, id) ((alpha)(id)) // The above mechanics require each permutation to // contain four elements, so we need to have four // input sequences. SEQ_FOR_EACH_PRODUCT will invoke // A with all possible combinations containing one // element from each input sequence. BOOST_PP_SEQ_FOR_EACH_PRODUCT( A, ( TYPE(c, char) TYPE(i, int) TYPE(f, float) ) ( TYPE(c, char) TYPE(i, int) TYPE(f, float) ) ( TYPE(c, char) TYPE(i, int) TYPE(f, float) ) ( TYPE(c, char) TYPE(i, int) TYPE(f, float) ) ) #undef A #undef B #undef C #undef TYPE A word of warning, however. What is being produced here is a combinatorial explosion and the algorithm is exponential. Therefore, if your sequences of types get longer and there are more of them, eventually the performance of the preprocessor will be so slow as to make this method of generation unusable. Regards, Paul Mensonides
Hi, This is becoming a little more clear what is going on. This is pretty cool.
A word of warning, however. What is being produced here is a combinatorial explosion and the algorithm is exponential. Therefore, if your sequences of types get longer and there are more of them, eventually the performance of the preprocessor will be so slow as to make this method of generation unusable.
The combinatorial explosion was the reason why I need this code generation, but you are right it can be pretty slow. Thanks again, Chris
"Paul Mensonides" wrote:
Chris Weed
I want to do something like use the following set of types TYPE1: char int float TYPE2: char int float double
to generate permutations of MyClass<TYPE1,TYPE2> such as
typedef MyClass<char,char> Mycc; typedef MyClass<char,int> Myci; typedef MyClass<char,float> Mycf;
[ snip code doing this ] Could the code be added into examples? People often wonder what the library could be used for and this is a perfect example. /Pavel
participants (3)
-
Chris Weed
-
Paul Mensonides
-
Pavel Vozenilek