
Hi all, I am trying to find a way to implement something like a preprocessing-time map. As far as I understand, the task is trivial if "keys" contain only one token: #define FIND(x) BOOST_PP_CAT(FIND_, x) #define FIND_key1 val1 #define FIND_key2 val2 #define FIND_key3 val3 And then: FIND(key1) // evaluates to val1 FIND(key2) // evaluates to val2 FIND(key3) // evaluates to val3 However, this approach obviously brakes when keys contain more than one token, like "key 1" (or, to be closer to the real problem, "unsigned int"). So I am wonderring if there is any facility in the preprocessor (or in the Boost.Preprocessor) that would allow me to do this. Thanks in advance, Arkadiy

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Arkadiy Vertleyb
I am trying to find a way to implement something like a preprocessing-time map. As far as I understand, the task is trivial if "keys" contain only one token:
However, this approach obviously brakes when keys contain more than one token, like "key 1" (or, to be closer to the real problem, "unsigned int").
It isn't usually the case that preprocessor metaprogramming is used to do type computation. It is possible, of course, given enough scaffolding, but templates are much more naturally suited to it. Types as values just doesn't scale with the preprocessor. It is common, OTOH, to generate a template-based solution with the preprocessor. Thus, what exactly are you trying to do?
So I am wonderring if there is any facility in the preprocessor (or in the Boost.Preprocessor) that would allow me to do this.
There isn't a facility to do it directly in the pp-lib, but it is possible. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> wrote
It isn't usually the case that preprocessor metaprogramming is used to do type computation. It is possible, of course, given enough scaffolding, but templates are much more naturally suited to it. Types as values just doesn't scale with the preprocessor. It is common, OTOH, to generate a template-based solution with the preprocessor. Thus, what exactly are you trying to do?
So I am wonderring if there is any facility in the preprocessor (or in the Boost.Preprocessor) that would allow me to do this.
There isn't a facility to do it directly in the pp-lib, but it is
I am trying to extend my typeof emulation system (see http://groups.yahoo.com/group/boost/files/typeof.zip) with the ability to conveniently support integral template parameters. I am generating partial template specializations that are responsible for encoding/decoding of a template instantiation. In such specialization, type parameters are handled differently from integral parameters in a few different aspects. I could encapsulate these aspects in a preprocessor tuple, and provide macros to generate these tuples, so that I would get something like this from the user: template<typename T, bool b, unsigned int n> class foo; REGISTER_TEMPLATE(foo, 3, ( TYPE_ARG, INTEGRAL_ARG(bool), INTEGRAL_ARG(unsigned int) )); // this expands into encoding/decoding specializations Here both TYPE_ARG and INTEGRAL_ARG(x) expand into a preprocessor tuple where all the necessary information is contained, so that I can generate my specializations. This looks implementable, but I am just trying to explore an alternative, where the user would just specify: REGISTER_TEMPLATE(foo, 3, (typename, bool, unsigned int)); And this requires to associate a few properties with, e.g., "unsigned int", which caused my original question. possible. Any information on the subject would be greatly appreciated. Thanks, Arkadiy

On Fri, 27 Aug 2004 02:00:35 -0400, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Paul Mensonides" <pmenso57@comcast.net> wrote
It isn't usually the case that preprocessor metaprogramming is used to do type computation. It is possible, of course, given enough scaffolding, but templates are much more naturally suited to it. Types as values just doesn't scale with the preprocessor. It is common, OTOH, to generate a template-based solution with the preprocessor. Thus, what exactly are you trying to do?
I am trying to extend my typeof emulation system (see http://groups.yahoo.com/group/boost/files/typeof.zip) with the ability to conveniently support integral template parameters. I am generating partial template specializations that are responsible for encoding/decoding of a template instantiation. In such specialization, type parameters are handled differently from integral parameters in a few different aspects. I could encapsulate these aspects in a preprocessor tuple, and provide macros to generate these tuples, so that I would get something like this from the user:
template<typename T, bool b, unsigned int n> class foo;
REGISTER_TEMPLATE(foo, 3, ( TYPE_ARG, INTEGRAL_ARG(bool), INTEGRAL_ARG(unsigned int) )); // this expands into encoding/decoding specializations
Here both TYPE_ARG and INTEGRAL_ARG(x) expand into a preprocessor tuple where all the necessary information is contained, so that I can generate my specializations.
This looks implementable, but I am just trying to explore an alternative, where the user would just specify:
REGISTER_TEMPLATE(foo, 3, (typename, bool, unsigned int));
And this requires to associate a few properties with, e.g., "unsigned int", which caused my original question.
So I am wonderring if there is any facility in the preprocessor (or in the Boost.Preprocessor) that would allow me to do this.
There isn't a facility to do it directly in the pp-lib, but it is possible.
Any information on the subject would be greatly appreciated.
Thanks, Arkadiy
I solved this version in the vintage version of typeof. I ended up defining three macros for encoding and three macros for decoding: (probably only need 2) //encoding classes #define BOOST_TYPEOF_typename_encode(arg) arg #define BOOST_TYPEOF_integral_encode(arg) integral_wrapper<arg> BOOST_PP_EMPTY() #define BOOST_TYPEOF_unsigned_integral_encode(arg) unsigned_integral_wrapper<arg> BOOST_PP_EMPTY() //Decoding templates #define BOOST_TYPEOF_typename_decode(n,text) ... #define BOOST_TYPEOF_integral_decode(n,text) ... #define BOOST_TYPEOF_unsigned_integral_decode(n,text) ... Use BOOST_TYPEOF_DECODE_ARGUMENT to create the correct decode macro, and BOOST_TYPEOF_ENCODE_ARGUMENT to encode it. Here is the source: // Copyright (C) 2004 Peder Holt // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_TYPEOF_TYPE_TO_MACRO_HPP_HOLT_2004_0827 #define BOOST_TYPEOF_TYPE_TO_MACRO_HPP_HOLT_2004_0827 #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/punctuation/paren.hpp> /* These macros are used to dechifer template arguments into sensible macros. There are three predefined macro builders: BOOST_TYPEOF_typename - for class and typename arguments BOOST_TYPEOF_integral - for signed integral values, int,short,char,bool, etc. BOOST_TYPEOF_unsigned_integral - for unsigned integral values, unsigned, unsigned long etc. All the fundamental integral types (except long long) have been pre-registered. In order to implement new template argument types (enums), you need to define a macro containing the name of the enum: enum MyEnum {red=0,green=1,blue=2}; #define BOOST_TYPEOF__MyEnum__ BOOST_TYPEOF_integral //MyEnum is now treated as an integral value in template expressions. template<MyEnum value> struct enum_class {}; //Is registered using BOOST_TYPEOF_DEFINE_TEMPLATE(enum_class,1,(MyEnum)) */ #define BOOST_TYPEOF_typename(dummy,append,arg) BOOST_PP_CAT(BOOST_TYPEOF_typename_,append)arg #define BOOST_TYPEOF_integral(dummy,append,arg) BOOST_PP_CAT(BOOST_TYPEOF_integral_,append)arg #define BOOST_TYPEOF_unsigned_integral(dummy,append,arg) BOOST_PP_CAT(BOOST_TYPEOF_unsigned_integral_,append)arg #define BOOST_TYPEOF__typename__ BOOST_TYPEOF_typename(dummy #define BOOST_TYPEOF__class__ BOOST_TYPEOF_typename(dummy #define BOOST_TYPEOF__bool__ BOOST_TYPEOF_integral(dummy #define BOOST_TYPEOF__char__ BOOST_TYPEOF_integral(dummy #define BOOST_TYPEOF__short__ BOOST_TYPEOF_integral(dummy #define BOOST_TYPEOF__int__ BOOST_TYPEOF_integral(dummy #define BOOST_TYPEOF__long__ BOOST_TYPEOF_integral(dummy #define BOOST_TYPEOF__unsigned__ BOOST_TYPEOF_unsigned_integral(dummy #define BOOST_TYPEOF__signed__ BOOST_TYPEOF_integral(dummy #define BOOST_TYPEOF__unsigned BOOST_TYPEOF_unsigned_integral( #define BOOST_TYPEOF__signed BOOST_TYPEOF_integral( #define BOOST_TYPEOF_ENCODE_ARGUMENT(z,n,text)\ BOOST_PP_CAT(BOOST_TYPEOF__,BOOST_PP_CAT(text,__)),encode,(BOOST_PP_CAT(A,n)) BOOST_PP_RPAREN() #define BOOST_TYPEOF_ENCODE_ARRAY_ELEMENT(z,n,array)\ BOOST_TYPEOF_ENCODE_ARGUMENT(z,n,BOOST_PP_ARRAY_ELEM(n, array)) #define BOOST_TYPEOF_DECODE_ARGUMENT(z,n,text)\ BOOST_PP_CAT(BOOST_TYPEOF__,BOOST_PP_CAT(text,__)),decode,(n,text) BOOST_PP_RPAREN() #define BOOST_TYPEOF_DECODE_ARRAY_ELEMENT(z,n,array)\ BOOST_TYPEOF_DECODE_ARGUMENT(z,n,BOOST_PP_ARRAY_ELEM(n, array)) #endif //BOOST_TYPEOF_TYPE_TO_MACRO_HPP_HOLT_2004_0827
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Peder Holt wrote:
I solved this version in the vintage version of typeof.
I ended up defining three macros for encoding and three macros for decoding: (probably only need 2)
[snip]
It's possible to make unrecognised types integral by default. This is a bit dodgy since it uses BOOST_PP_SEQ_HEAD in an unintended manner, and uses BOOST_PP_IS_UNARY which is not part of the public interface and currently not available on all compilers (this might change). Also, BOOST_PP_IS_UNARY is unstable, Paul Mensonides wrote:
Regarding the instability: the macro itself is stable, but the input is not which can foul up the internals. The library itself does a ton of extra scaffolding to force expansion order when it is important (for VC and MWCW < 9) it does this globally across the entire library. However, that scaffolding does not exist in user code (nor should it have to if at all possible), and IS_UNARY (etc.) cannot force an arbitrary amount of expansion to account for it. You'd be surprise how much stuff doesn't expand when it should on those preprocessors that happens to get picked up later. (You might have guessed that I really really hate those preprocessors.)
http://lists.boost.org/MailArchives/boost/msg69412.php I've been doing this kind of thing in some of my own code, and it does cause problems. Hopefully, in this case, since you're not doing much processing on the arguments, BOOST_PP_CAT will do the sufficient expansion. Anyway, here's the code: #include <boost/preprocessor/control/iif.hpp> #include <boost/preprocessor/detail/is_unary.hpp> #include <boost/preprocessor/seq/seq.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/static_assert.hpp> // Register the basic values: #define BOOST_TYPEOF_typename (typename) #define BOOST_TYPEOF_class (typename) #define BOOST_TYPEOF_unsigned (unsigned) // Check if the argument matches a registered type. #define BOOST_TYPEOF_ARG_TYPE(x) \ BOOST_PP_IIF(BOOST_PP_IS_UNARY(BOOST_PP_CAT(BOOST_TYPEOF_, x)), \ BOOST_TYPEOF_ARG_TYPE_MATCHED, \ BOOST_TYPEOF_ARG_TYPE_UNMATCHED)(x) #define BOOST_TYPEOF_ARG_TYPE_MATCHED(x) \ BOOST_PP_SEQ_HEAD(BOOST_PP_CAT(BOOST_TYPEOF_, x)) // The default value: #define BOOST_TYPEOF_ARG_TYPE_UNMATCHED(x) integral // Examples of use: BOOST_TYPEOF_ARG_TYPE(typename) // = typename BOOST_TYPEOF_ARG_TYPE(class) // = typename BOOST_TYPEOF_ARG_TYPE(unsigned int) // = unsigned BOOST_TYPEOF_ARG_TYPE(int) // = integral BOOST_TYPEOF_ARG_TYPE(new_type) // = integral // Add a custom type: #define BOOST_TYPEOF_new_type (unsigned) BOOST_TYPEOF_ARG_TYPE(new_type) // = unsigned
participants (4)
-
Arkadiy Vertleyb
-
Daniel James
-
Paul Mensonides
-
Peder Holt