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 19:01:05


Never mind the issue, in the end it turns out I had forgotten to
re-enter the #include for BOOST_PP_SEQ_SIZE.

Thanks!
Geoff

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