简体   繁体   中英

C/C++ expand multiple macros into one variadic macro

Background

I am working on an existing codebase which uses a macro pattern to generate boilerplate methods similar to this:

START_MAP()
  MAP_ENTRY(a)
  MAP_ENTRY(b)
  // .....
  MAP_ENTRY(z)
END_MAP()

I am re-implementing the code that these macros generate, but I can not touch this pattern because that would require large refactors. I need to expand this pattern into a macro (which I define) which we will call NEW_IMPLEMENT which is a variadic macro that is called like so: NEW_IMPLEMENT(a, b, ..., z) .

Problem

How can I redefine START_MAP , MAP_ENTRY , and END_MAP so that the pattern as it currently exists expands to NEW_IMPLEMENT(a, b, ..., z) ?

What I have tried so far

#define NEW_IMPLEMENT(...) ...
#define START_MAP NEW_IMPLEMENT(
#define MAP_ENTRY(x) x,
#define END_MAP )

This throws a preprocessor error, however: error: unterminated argument list invoking macro "NEW_IMPLEMENT"

You can make the pattern expand to NEW_IMPLEMENT(stuff) text , but the resulting macro will not be expanded - C preprocessor does not rescan results from multiple macro expansions together.

You can "join" them, by wrapping everything in another macro call which will force another pass over all the results. And also you need to pass the paren as a token, not literally, so that you don't get unterminated call.

#define CALL(...)   __VA_ARGS__

#define PAREN (
#define START_MAP()   NEW_IMPLEMENT PAREN
#define END_MAP()   )
#define MAP_ENTRY(a)  a,

#define NEW_IMPLEMENT(...)  "Hello: " #__VA_ARGS__

CALL(
START_MAP()
  MAP_ENTRY(a)
  MAP_ENTRY(b)
  // .....
  MAP_ENTRY(z)
END_MAP()
)

But overall, I do not understand. I would prefer to refactor the code with a simple sed 's/START_MAP()/NEW_IMPLEMENT(/; s/MAP_ENTRY(a)/a,/; s/END_MAP()/)/' for code readability and maintainability. I do not think "not touching ancient code" is a good enough reason for making the codebase more convoluted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM