The preprocessor doesn't have any way to do anything with character literals like 'a'
other than output them as is, so I don't think that form is possible. Instead, we'll need to work with identifier preprocessor tokens like a
.
Working with numbers in the preprocessor is always tricky, but Boost.Preprocessor has tools to help.
#include <boost/preprocessor/seq/cat.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/facilities/overload.hpp>
#define REPEAT_MACRO_SEQ_ELEM(z, n, data) (data)
#define REPEAT_MACRO_2(c, n) \
BOOST_PP_SEQ_CAT(BOOST_PP_REPEAT(n, REPEAT_MACRO_SEQ_ELEM, c))
#define REPEAT_MACRO_1(c) c
#define REPEAT_MACRO(...) \
BOOST_PP_OVERLOAD(REPEAT_MACRO_, __VA_ARGS__)(__VA_ARGS__)
I've renamed your macro REPEAT_MACRO
, because it's common practice to use only uppercase for a preprocessor macro name, giving a hint to the code reader that it's a macro.
REPEAT_MACRO_2
uses BOOST_PP_SEQ_CAT
to paste together a sequence of preprocessor tokens. It expects input in the form of a "sequence" like (a)(a)(a)(a)(a)
, so we pass it the result of BOOST_PP_REPEAT
, using REPEAT_MACRO_SEQ_ELEM
as the operator to add the parentheses around the input token.
To take care of allowing REPEAT_MACRO(r)
producing just r
, there's BOOST_PP_OVERLOAD
. It will paste the number of arguments onto the end of the given macro prefix REPEAT_MACRO_
, so that REPEAT_MACRO(c)
calls REPEAT_MACRO_1(c)
and REPEAT_MACRO(c,n)
calls REPEAT_MACRO_2(c,n)
.
This solution doesn't really require that the input identifier is just one character, and I'm not sure there's any way to require that. So you also get that REPEAT_MACRO(xyz, 3)
gives xyzxyzxyz
.
For the case from comments of repeating a *
as in function type int repeatMacro(*, 2) func()
, you would not want to concatenate the preprocessor tokens, since there's no such token as **
. To get that behavior instead of the identifier-pasting would be instead:
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/facilities/overload.hpp>
#define REPEAT_MACRO_ID_OP
#define REPEAT_MACRO_2(c, n) BOOST_PP_REPEAT(n, REPEAT_MACRO_ID_OP, c)
#define REPEAT_MACRO_1(c) c
#define REPEAT_MACRO(...) \
BOOST_PP_OVERLOAD(REPEAT_MACRO_, __VA_ARGS__)(__VA_ARGS__)
I doubt there's any way to get a single macro doing the paste for identifiers and just repetition for punctuation.