Boost logo

Boost Users :

Subject: Re: [Boost-users] [preprocessor] It works, but how can I make it better/more elegant?
From: Daniel Bradburn (moagstar_at_[hidden])
Date: 2010-07-29 03:27:11


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 pairstypedef 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;
"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?"
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_at_[hidden]
> From: geoff.hilton_at_[hidden]
> 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_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
                                               



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net