I want to generate several pieces of code for several different values using the C++ preprocessor. I entered all of these values into a table generation macro. However, some parts of the code only have to be generated for certain (disjunct) subsets of the values. Hence, I would like to have small table generation macros and then merge them together into a large one (for the code that has to be generated for all of them). This part works flawlessly so far.
However, I require to use a comma as a seperator for some parts of the code (precisely to generate an enum). Unfortunately, this comma is replaced too early (i.e. before the function call of the macro is replaced). Here comes an example which should illustrate my problem:
#include <iostream>
#define A(F, SEP) F(one) SEP F(two)
#define B(F, SEP) F(three) SEP F(four)
#define C(F, SEP) A(F, SEP) SEP B(F, SEP)
#define SOME_F(x) x
#define SOME_SEP ,
enum {C(SOME_F, SOME_SEP)} ENUM;
int main()
{
#define ANOTHER_F(x) std::cout << #x << std::endl;
#define ANOTHER_SEP
A(ANOTHER_F, ANOTHER_SEP)
return 0;
}
Here I want to generate an enum containing all values (it's unused in the example but in my actual code I require it) and print all values of the subset A. If I try to compile this example, it fails with the error error: macro "A" passed 3 arguments, but takes just 2
(same message for B). The reason for this seems to be, that the SOME_SEP
macro is replaced before A
is substituted (and an attempt to use A(F, ,)
is made).
A rather simple (but ugly) fix for this is to replace the SEP argument to be a function-like instead of an object-like macro (one has to add parentheses to each call though). However, I would like to solve this using an object-like macro. During my web search I discovered a lot of people with a similar problem, but they wanted to pass a template-type (and hence can resolve the issue by using braces (which doesn't work for the comma as a seperator)).