[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
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
supported_types_map; } //namespace blah
Thank you! Geoff
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@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
, bmpl::pair , bmpl::pair , bmpl::pair 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
) \ /**/ #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
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;
Oh nice! I don't know why I never noticed the lack of commas between items in sequences, must be psychological.
"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;
Love it! I'm glad the preprocessor ignores underlying types of typedefs, because some of those value types are typedefs of eachother, but with different array classes. :S I'm doing my best to remain on the same conceptual level of abstraction for types as this third party. Thanks very much for your input! Geoff
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
, bmpl::pair , bmpl::pair , bmpl::pair 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
) \ /**/ #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
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@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
, bmpl::pair , bmpl::pair , bmpl::pair 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
) \ /**/ #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
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@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
, bmpl::pair , bmpl::pair , bmpl::pair 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
) \ /**/ #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
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@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
, bmpl::pair , bmpl::pair , bmpl::pair 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
) \ /**/ #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
participants (2)
-
Daniel Bradburn
-
Geoff Hilton