Assume I have a variadic template:
template<typename... Args>
class Foo;
This variadic template generates another template recursively until it reaches the one argument Foo
in the last level. Now I want to have a macro for example Bar(...)
which when I call it I get something like this:
Bar(float, int, string, vector<int>)
// expands to
Macro(Foo<float, int, string, vector<int>>)
Macro(Foo<int, string, vector<int>>)
Macro(Foo<string, vector<int>>)
Macro(Foo<vector<int>>)
Which Macro(...)
is another macro for doing something on this class. I hope to able to use Boost Preprocessor to reduce the code I have to write.
Please suggest me some tips that helps me to write such macro.
I don't know if this is the best approach to solving your problem but this does what you want:
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/seq.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#define CALL_MACRO(_,__,SEQ) Macro(Foo<BOOST_PP_SEQ_ENUM(SEQ)>)
#define GENERATE_MACRO_INVOCATIONS(SEQS) BOOST_PP_SEQ_FOR_EACH(CALL_MACRO,_,SEQS)
#define GENERATE_DESCENDING_SEQUENCES(_,INDEX,DATA) (BOOST_PP_SEQ_REST_N(INDEX,DATA))
#define BAR_IMPL(SEQ) GENERATE_MACRO_INVOCATIONS(BOOST_PP_REPEAT_FROM_TO(0,BOOST_PP_SEQ_SIZE(SEQ),GENERATE_DESCENDING_SEQUENCES, SEQ))
#define Bar(...) BAR_IMPL(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
Bar(float, int, string, vector<int>)
float, int, string, vector<int>
.BOOST_PP_VARIADIC_TO_SEQ
transforms it to: (float)(int)(string)(vector<int>)
BOOST_PP_REPEAT_FROM_TO
calls the macro GENERATE_DESCENDING_SEQUENCES
BOOST_PP_SEQ_SIZE(SEQ)
times with the sequence as data and an index that starts from 0.BOOST_PP_SEQ_REST_N(INDEX,DATA)
removes the INDEX
first elements from DATA
and returns the rest. This result is put inside a couple of parentheses.After the invocation of the REPEAT you have a sequence of sequences:
((float)(int)(string)(vector))((int)(string)(vector))((string)(vector))((vector))
BOOST_PP_SEQ_FOR_EACH
calls CALL_MACRO
with every element in the sequence of sequences.
BOOST_PP_SEQ_ENUM
takes a sequence and returns its elements separated by commas.