'Macro to repeat a single character multiple number of times
I am learning about macros and I want to know that whether it is possible to create a macro that repeats a given character literal a given number of times. For example:
Input:
repeatMacro('a', 5)
should produce(expand to) the output:
Expected Output:
aaaaa
Similarly, repeatMacro('r', 2)
should produce:
rr
If possible, repeatMacro('r')
should produce(expand to):
r
I have not worked with macros before so I don't know if this is a very basic thing to do.
I also don't know if there is any other way(other than macros) to do the same. If there is any other way(other than macro) to do this, I would prefer that way instead of using macros.
For example, I know that we can do things like the following with macros:
#define x *
int x func()
{
int*ptr = new int(4);
return ptr;
}
So I want to do the same with repeatMacro
. Something like shown below:
#define repeatMacro(str, n) // what should come here for the below example to work
int repeatMacro('*',2) func()
{
int** ptr = new int*[5]();
return ptr;
}
Solution 1:[1]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |