I am looking for a variadic C preprocessor macro that passes its argument and a corresponding format string to a function, repeating a character depending on the number of arguments.
For example, I would like a macro FOO
which expands as follows (or to equivalent C code):
FOO(1)
→ bar("d",1)
FOO(1,2)
→ bar("dd",1,2)
,FOO(1,2,3)
→ bar("ddd",1,2,3)
FOO()
→ bar("")
While I can combine the solutions to C preprocessor macro for returning a string repeated a certain number of times and C++ preprocessor __VA_ARGS__ number of arguments (or similar questions) or use variadic macros, these have several drawbacks such as:
My hope is that some better solutions emerge when these problems are not regarded separately.
I want to callback Python functions in a C extension of Python in automatically generated code.
So, for example, I need foo(1,2,3)
to expand to:
PyObject_CallObject( callback_foo, Py_Build_Value("(Oddd)",Y,1,2,3) )
I know that all arguments of foo
are doubles, but I do not know their number.
(The above example is somewhat simplified. I am aware that it is missing a few Py_DECREF
s.)
The best I could come up with so far is to take this answer and simplify it:
# define EXPAND(x) x
# define FORMATSTRING(...) EXPAND(ELEVENTHARG1(__VA_ARGS__ __VA_OPT__(,) RSEQ()))
# define ELEVENTHARG1(...) EXPAND(ELEVENTHARG2(__VA_ARGS__))
# define ELEVENTHARG2(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N
# define RSEQ() "dddddddddd","ddddddddd","dddddddd", \
"ddddddd","dddddd","ddddd","dddd","ddd","dd","d",""
# define FOO(...) bar( FORMATSTRING(__VA_ARGS__) __VA_OPT__(,) __VA_ARGS__ )
FOO() // expands to: bar( "" )
FOO(1) // expands to: bar( "d" , 1 )
FOO(1,2,3) // expands to: bar( "ddd" , 1,2,3 )
This works with GCC and Clang (with -std=c++2a
) and up to ten arguments (but can be expanded).
The biggest compatibility issue are the two instances of __VA_OPT__(,)
, which are only required for handling the zero-argument case.
Otherwise, they can be replaced by a simple ,
.