I would like to write a preprocessor macro that does one thing if it's argument is a parenthesized tuple of tokens, like this:
MY_MACRO((x, y))
and something else if it's just a single token, like this:
MY_MACRO(x)
Is that possible?
How about distinguishing between the number of space-separated tokens, i.e. between MY_MACRO(x)
and MY_MACRO(x y)
?
Note that I am not trying to overload based on the number of arguments - it's a unary macro in all cases.
EDIT: I am willing to use variadic macros if they help
Operator overloading only applies to C++ functions and not to macros. Consider that macros are expanded by the preprocessor and and are hence are no longer visible to the following compilation steps.
Function-like macros can take arguments, just like true functions. To define a macro that uses arguments, you insert parameters between the pair of parentheses in the macro definition that make the macro function-like. The parameters must be valid C identifiers, separated by commas and optionally whitespace.
For portability, you should not have more than 31 parameters for a macro. The parameter list may end with an ellipsis (…). In this case, the identifier __VA_ARGS__ may appear in the replacement list.
Macro Arguments (DEFINE-! ENDDEFINE command) The macro definition can include macro arguments, which can be assigned specific values in the macro call. There are two types of arguments: keyword and positional. Keyword arguments are assigned names in the macro definition; in the macro call, they are identified by name.
As for your first question, the following macros might meet your purpose:
#define CONCAT_( x, y ) x ## y
#define CONCAT( x, y ) CONCAT_( x, y )
#define IS_SINGLE_1(...) 0
#define IGNORE(...)
#define IS_SINGLE_2_0 0 IGNORE(
#define IS_SINGLE_2_IS_SINGLE_1 1 IGNORE(
#define IS_SINGLE( x ) CONCAT( IS_SINGLE_2_, IS_SINGLE_1 x ) )
IS_SINGLE((x, y)) // 0
IS_SINGLE(x) // 1
Macro IS_SINGLE
is expanded to 1 if the argument is single token,
otherwise, 0.
Hope this helps
Using boost.preprocessor
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define SEQ (w)(x)(y)(z)
#define MACRO(r, data, elem) BOOST_PP_CAT(elem, data)
BOOST_PP_SEQ_FOR_EACH(MACRO, _, SEQ) // expands to w_ x_ y_ z_
It's not exactly the same as even a single argument case requires parenthesis. But It does allow a variable number of parenthesized arguments.
Also a possibility: Use the BOOST_PP_IF, BOOST_PP_EQUAL, and BOOST_PP_TUPLE_ELEM to do something like:
MACRO(1, a)
MACRO(2, (a,b) )
MACRO(3, (a,b,c) )
or so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With