ForgottenCat's blog

By ForgottenCat, history, 3 months ago, In English

We will use __COUNTER__ and a #define, so it would eventually duplicates given parameter N times. I can't give you a macro that just REPEAT(100, abcd) and will expand to 100*abcd without defining 100 lines of macro. If you don't want to see how it works, scroll down to the bottom.

Firstly, let's see this technique:

#define EXP(...) EXP1(EXP1(EXP1(EXP1(__VA_ARGS__))))
#define EXP1(...) EXP2(EXP2(EXP2(EXP2(__VA_ARGS__))))
#define EXP2(...) EXP3(EXP3(EXP3(EXP3(__VA_ARGS__))))
#define EXP3(...) EXP4(EXP4(EXP4(EXP4(__VA_ARGS__))))
#define EXP4(...) __VA_ARGS__ // Just expand it lots of times.

#define REP() 1 DEFER(REP_I)()()
#define EMPTY()
#define DEFER(...) __VA_ARGS__ EMPTY()
#define REP_I() REP

EXP(REP())

If you expand the EXP(REP()), you will see a lot of 1. Why? Because the macro DEFER() make it so that REP can be expanded many times within a single macro. Just like void dfs() { cout << 1; dfs();}. But this also has an end: it depends on how many time you expand it. That's why we added lots of EXP(). You can even add EXP5 and more, but you'll probably start lagging. Also you can try expand it for 1 or 2 times to see the difference.

Also that's how the SP() macro made in my template.

But how to make it stop? We can use __COUNTER__. After certain times of expansion, the __COUNTER__ will reach a certain value, then we can make it stop.

#include <bits/stdc++.h>
using namespace std;
#define EXP(...) EXP1(EXP1(EXP1(EXP1(__VA_ARGS__))))
#define EXP1(...) EXP2(EXP2(EXP2(EXP2(__VA_ARGS__))))
#define EXP2(...) EXP3(EXP3(EXP3(EXP3(__VA_ARGS__))))
#define EXP3(...) EXP4(EXP4(EXP4(EXP4(__VA_ARGS__))))
#define EXP4(...) __VA_ARGS__

#define EMPTY(...)
#define DEFER(...) __VA_ARGS__ EMPTY()
#define CONCAT(A, B) CCONCAT(A, B)
#define CCONCAT(A, B) A##B
#define SECO(A, B, ...) B
#define BASE(B) , DEFER(REP_I)()(__COUNTER__, B)
#define REP(A, B) B DEFER(SECO)(CONCAT(REP_, A), BASE)(B)
#define REP_I() REP

#define rep(A) EXP(REP(__COUNTER__, A))

#define REP_29 A, EMPTY
#define REP_59 A, EMPTY
#define REP_99 A, EMPTY

int a[]{rep(1)};
int b[]{rep(1)};
int c[]{rep(3)};

int main()
{
	cout << size(a) << endl; // 30
	cout << size(b) << endl; // 30
	cout << size(c);         // 40
}

To use this, assume current __COUNTER__ value is x, then #define REP_X+N-1 A, EMPTY, so the given macro A will expand N times. Then x will add N.

To customize separator, see the part: #define BASE(B) , and change the comma to anything else.

If you see it expand to something else at the end, you need to add more EXP. Currently it can repeat at most 171 times using one rep. Change REP_99 to REP_230 and REP_231 to see.

  • Vote: I like it
  • +3
  • Vote: I do not like it

»
3 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by ForgottenCat (previous revision, new revision, compare).