Boost logo

Boost Users :

Subject: Re: [Boost-users] [preprocessor] It works, but how can I make it better/more elegant?
From: Geoff Hilton (geoff.hilton_at_[hidden])
Date: 2010-07-29 13:57:12


Umm.. I copy/pasted your code and I get warnings, basically the
preprocessor doesn't give the expected output. I'm using Visual Studio
2008 SP1, what about you? I noticed one difference in your
implementation is that you don't add parentheses around the sequence as
a whole before passing it in as a parameter, whereas with my old
implementation, without the quotes around the sequence it wouldn't work.
What are you using, and is it a compiler quirk or am I missing something?

Geoff

On 29/07/2010 3:27 AM, Daniel Bradburn wrote:
> 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;
>
> "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 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