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 14:14:10


Where I said quotes, I meant parentheses. :)

On 29/07/2010 1:57 PM, Geoff Hilton wrote:
> 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