Is variational macro substitution possible for each argument?

I have read quite a few questions about SO about variable macros now, but it seems that no one has answered the simplest question:

#define IDENTITY(x) x #define IDENTITY_FOR_ALL(...) ??? 

Is there a way to make IDENTITY_FOR_ALL expand to IDENTITY(X) for all arguments? Is any number of arguments possible?

+5
source share
2 answers

There is no such thing as a package extension for variable arrays, as well as for variable templates.

However, you can use Boost.Preprocessor (or its methods).

If you don't need any commas between elements, use

 #include <boost/preprocessor/seq/for_each.hpp> #include <boost/preprocessor/variadic/to_seq.hpp> #define ID_OP(_, func, elem) func(elem) #define APPLY_TO_ALL(func, ...) \ BOOST_PP_SEQ_FOR_EACH( \ ID_OP, func, \ BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \ ) // example call: #define SomeTransformation(x) #x // stringize the argument APPLY_TO_ALL(SomeTransformation, 1, 2, 3) // expands to "1" "2" "3" 

Demo With commas:

 #include <boost/preprocessor/seq/enum.hpp> #include <boost/preprocessor/seq/transform.hpp> #include <boost/preprocessor/variadic/to_seq.hpp> #define ID_OP(_, func, elem) func(elem) #define APPLY_TO_ALL(func, ...) \ BOOST_PP_SEQ_ENUM( \ BOOST_PP_SEQ_TRANSFORM( \ ID_OP, func, \ BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \ )) // example call: APPLY_TO_ALL(SomeTransformation, 1, 2, 3) // expands to "1", "2", "3" 

Demo Check the preprocessor output with g++ -std=c++11 -E -P file .

+3
source

Assuming you need a PP solution, you can use BOOST_PP_REPEAT :

 //invoke IDENTITY_FOR_ALL_MACRO with each index and the given tuple #define IDENTITY_FOR_ALL(...) \ BOOST_PP_REPEAT( \ BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \ IDENTITY_FOR_ALL_MACRO, \ BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \ ) //use the index to access the right element of the passed tuple #define IDENTITY_FOR_ALL_MACRO(z, n, data) \ IDENTITY(BOOST_PP_TUPLE_ELEM(n, data)) IDENTITY_FOR_ALL(abc, 123, "woopee") //translated to abc 123 "woopee" 

It would be wise to just turn this into a more general macro that accepts the macro to call, and the list of single arguments is passed one by one if you need to do this with several different macros, not just IDENTITY .

I'm not 100% sure what you mean by an arbitrary number of arguments, but if you want to call IDENTITY with two arguments at the same time, and not with one, you can change the bottom macro to use BOOST_PP_MUL and BOOST_PP_INC to access "2n" th and The "2n + 1" th elements of the tuple, and then call the macro only half the size of the REPEAT call.

+1
source

Source: https://habr.com/ru/post/1205132/


All Articles