The following is probably a cleaner way of achieving the same result:
// Pass the sequence in as the additional data - then access the nth element which
// will be your tuple. This can then be split into it's individual elements
#define TEST_PP_GENERATE_SUPPORTED_TYPE_PAIR(z, n, seq) \
boost::mpl::pair< \
BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_SEQ_ELEM(n, seq)), \
BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_SEQ_ELEM(n, seq))>
// You don't need to separate the elements of a sequence with commas, which
// is probably why it wasn't working with BOOST_PP_SEQ_SIZE
#define TEST_PP_SUPPORTED_TYPES \
((SomeIntArray, SomeInt)) \
((SomeDoubleArray, SomeDouble)) \
((SomBoolArray, SomeBool)) \
((SomeOtherClassArray, SomeOtherClass))
// Generate the pairs
typedef boost::mpl::map
<
BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(TEST_PP_SUPPORTED_TYPES),
TEST_PP_GENERATE_SUPPORTED_TYPE_PAIR, TEST_PP_SUPPORTED_TYPES)
>
supported_types_map;
Yes otherwise the preprocessor thinks that they are the parameters to be passed to a macro.
If you can guarentee some continuity with the names of these types, then you could simplify it further, e.g.
// You can generate the second parameter from the element name
#define TEST_PP_GENERATE_SUPPORTED_TYPE_PAIR(z, n, seq) \
boost::mpl::pair< \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(n, seq), Array), \
BOOST_PP_SEQ_ELEM(n, seq)>
#define TEST_PP_SUPPORTED_TYPES \
(SomeInt) \
(SomeDouble) \
(SomeBool) \
(SomeOtherClass)
typedef boost::mpl::map
<
BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(TEST_PP_SUPPORTED_TYPES),
TEST_PP_GENERATE_SUPPORTED_TYPE_PAIR, TEST_PP_SUPPORTED_TYPES)
>
supported_types_map;
> To: boost-users@lists.boost.org
> From: geoff.hilton@t-optlogic.com
> Date: Wed, 28 Jul 2010 13:47:56 -0400
> Subject: [Boost-users] [preprocessor] It works, but how can I make it better/more elegant?
>
> Yay! I finally got my type map generating code to work! There has got to
> be a better way though because it feels really kludgey. Opinions? If you
> have a more elegant way of accomplishing the same thing (without
> misusing BOOST_PP_APPLY as I think I did, because I only used it to
> remove the extra pair of parens surrounding the tuple in
> TEST_PP_get_type, something that, oddly, BOOST_PP_TUPLE_REM_CTOR doesn't
> succeed at doing (at least not without breaking the current code).
>
> Was I correct in my assumption (which is why I handled it the way I did
> in my below code) that basically anytime a a comma appears, the two
> surrounding tokens must be treated as a tuple (and thus parenthesized?
> This is what I've gathered from the online documentation as well as the
> "C++ Template Metaprogramming" book.
>
> The purpose of this code is to create a type map between array types and
> corresponding value types of 3rd party classes which don't conform at
> all to STL usage practices, that which I'd like to use, so I'm writing
> an array wrapper template class with associated iterator template
> classes using iterator_facade & the MPL. The map generated by this code
> is used to map between array and value types for type selection purposes.
>
> The following (reformatted for readability) code should generate this
> (also reformatted) preprocessed output, though I've only tested the real
> code and not this that is mostly copy/pasted:
>
> typedef bmpl::map<
> bmpl::pair<SomeIntArray, SomeInt>,
> bmpl::pair<SomeDoubleArray, SomeDouble>,
> bmpl::pair<SomeBoolArray, SomeBool>,
> bmpl::pair<SomeOtherClassArray, SomeOtherClass>
> > supported_types_map;
>
> --test.hpp--
> (omitting #inclusions)
> namespace blah {
> namespace bmpl = boost::mpl;
>
> //must match size as below tuples in sequence for readability.
> #define TEST_PP_tuple_size 2
>
> //index of array type inside tuple for readability.
> #define TEST_PP_array_descriptor 0
>
> //index of value type inside tuple for readability.
> #define TEST_PP_value_descriptor 1
> //sequence of tuples of supported types
> #define TEST_PP_supported_types \
> ((SomeIntArray, SomeInt)) \
> ,((SomeDoubleArray, SomeDouble)) \
> ,((SomBoolArray, SomeBool)) \
> ,((SomeOtherClassArray, SomeOtherClass))\
> /**/
>
> //size of TEST_PP_supported_types (BOOST_PP_SEQ_SIZE doesn't work on it)
> #define TEST_PP_types_size 4
>
> #define TEST_PP_get_type(index, type_descriptor) \
> BOOST_PP_TUPLE_ELEM(TEST_PP_types_tuple_size, \
> type_descriptor, \
> TEST_PP_get_tuple(index) \
> ) \
> /**/
>
> //gets tuple from TEST_PP_supported_types
> #define TEST_PP_get_tuple(index) \
> BOOST_PP_APPLY( \
> BOOST_PP_TUPLE_ELEM( \
> TEST_PP_types_size, index, (TEST_PP_supported_types)\
> ) \
> ) \
> /**/
>
> //this returns a tuple containing the first and last part of the mpl::pair
> #define TEST_PP_bmpl_pair(index) \
> (bmpl::pair<TEST_PP_get_type(index, TEST_PP_array_descriptor), \
> TEST_PP_get_type(index, TEST_PP_value_descriptor)>) \
> /**/
>
> #define TEST_PP_pair_fwder(next_index, index, data) \
> BOOST_PP_TUPLE_REM_CTOR(2,TEST_PP_bmpl_pair(index)) \
> /**/
>
> typedef bmpl::map<
> BOOST_PP_ENUM(TEST_PP_types_size, TEST_PP_pair_fwder, ~)
> > supported_types_map;
> } //namespace blah
>
>
>
> Thank you!
> Geoff
>
> _______________________________________________
> Boost-users mailing list
> Boost-users@lists.boost.org
> http://lists.boost.org/mailman/listinfo.cgi/boost-users