0

I want to create a macro in which one of the parameters is the parameters for a function used within the macro.

#define Macro(PERAMS, OTHER) \
    functionBeingUsed(PERAMS); \
    OTHER; 


Macro(1,2,3,4, int i = 0);

As you can see you can see the commas are being used by both the macro and the function. which results in broken code.

I was wondering if there was a way to achieve the result that I need so the code can be interpreted like the following.

Macro((1,2,3,4), int i = 0);

Please note I am not using C++11.

ZNackasha
  • 755
  • 2
  • 9
  • 29

5 Answers5

2

Whenever you need to do anything nontrivial with the preprocessor, you should immediately jump to the Boost.PP library. Here, the BOOST_PP_REMOVE_PARENS macro seems relevant:

#define Macro(PARAMS, OTHER) \
    functionBeingUsed(BOOST_PP_REMOVE_PARENS(PARAMS)); \
    OTHER; 

Macro((1,2,3,4), int i = 0);

Alternatively, you could just write functionBeingUsed PARAMS and let the passed parentheses be used.

o11c
  • 15,265
  • 4
  • 50
  • 75
1

It is not possible to do what you have described. However, you can do something similar with variadic macros. You would need to put the PARAMS part at the end and it would look like the following:

#define Macro(OTHER, ...) \
    functionBeingUsed(__VA_ARGS__); \
    OTHER;

Macro(int i = 0, 1, 2, 3, 4);
mikebob
  • 311
  • 1
  • 5
  • Sorry that i did not say this but I am not using c++ 11. – ZNackasha Jun 25 '18 at 23:38
  • This is why variadic macros were added, because it wasn't possible before. – Barmar Jun 25 '18 at 23:50
  • 1
    Variadic macros were also part of C99, which technically isn't necessarily part of C++, but many compilers support the above syntax even without being in C++11 mode. – mikebob Jun 26 '18 at 00:09
  • It is possible, see my answer. – o11c Jun 26 '18 at 00:36
  • @o11c: You change the call syntax though. Mine uses OP syntax (and supports it up to hard coded value). – Jarod42 Jun 26 '18 at 10:15
  • @Jarod42 changing the order is a bigger deal ... actually, by dispatching based on the number of arguments, I suppose it *is* technically possible to preserve the exact syntax ... – o11c Jun 26 '18 at 15:13
0

I believe the only answer is to use multiple macros

#define MacroBegin \
   \\PreFunction

#define MacroEnd \
   \\PostFunction

MacroBegin
functionBeingCalled(1,2,3,4);
MacroEnd
ZNackasha
  • 755
  • 2
  • 9
  • 29
  • And how does this address the OP's issue exactly? – Remy Lebeau Jun 26 '18 at 01:23
  • @RemyLebeau It's a common and useful technique, especially with longer bodies, since it doesn't mess up line numbers during macro expansion. Though using an "x-macros" .def header may be a better option. – o11c Jun 26 '18 at 02:36
0

To differentiate which commas belong to the macro itself and which belong to the function being called, you have to wrap the function parameters in parenthesis, eg:

Macro((1,2,3,4), int i = 0);

You would then have to remove the parenthesis from the function call inside the macro, since they will be coming from the macro parameter instead, eg:

#define Macro(PERAMS, OTHER) \
    functionBeingUsed PERAMS; \
    OTHER; 

So, something like this:

Macro((1,2,3,4), int i = 0);

Will resolve to this:

functionBeingUsed (1,2,3,4);
int i = 0; 

Just remember the extra parenthesis even if the function being called doesn't take any input parameters:

Macro((), ...);

functionBeingUsed ();
...; 
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

To keep your syntax, you may do something like:

#define COUNT_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...)    N
#define COUNT(...)   COUNT_N(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
// Warning: COUNT() return 1 (as COUNT(A)) :-/

#define IDENTITY(N) N
#define APPLY(macro, ...) IDENTITY(macro(__VA_ARGS__))

#define F_1(a) functionBeingUsed(); a;
#define F_2(a, b) functionBeingUsed(a); b;
#define F_3(a, b, c) functionBeingUsed(a, b); c;
#define F_4(a, b, c, d) functionBeingUsed(a, b, c); d;
#define F_5(a, b, c, d, e) functionBeingUsed(a, b, c, d); e;
#define F_6(a, b, c, d, e, f) functionBeingUsed(a, b, c, d, e); f;
#define F_7(a, b, c, d, e, f, g) functionBeingUsed(a, b, c, d, e, f); g;
#define F_8(a, b, c, d, e, f, g, h) functionBeingUsed(a, b, c, d, e, f, g); h;

#define DISPATCH(N) F_ ## N

#define Macro(...) IDENTITY(APPLY(DISPATCH, COUNT(__VA_ARGS__)))(__VA_ARGS__)

Demo

but simpler to change your syntax to:

#define Macro(PARAMS, OTHER)  \
    functionBeingUsed PARAMS; \
    OTHER;

Macro((1,2,3,4), int i = 0);
Jarod42
  • 203,559
  • 14
  • 181
  • 302