'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