Is variadic macro subsitution for every argument possible? - c++

I read quite a few questions on SO about variadic macros now, but it doesn't seem like anyone answered the most simple question:
#define IDENTITY(x) x
#define IDENTITY_FOR_ALL(...) ???
Is there a way to make IDENTITY_FOR_ALL expand to IDENTITY(X) for all arguments? Is it also possible for arbitrary numbers of arguments?

There is no such thing as a pack expansion for variadic macros as there is for variadic templates.
You could use Boost.Preprocessor (or its methods) though.
If you don't want any commas between the elements, use
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#define ID_OP(_, func, elem) func(elem)
#define APPLY_TO_ALL(func, ...) \
BOOST_PP_SEQ_FOR_EACH( \
ID_OP, func, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \
)
// example call:
#define SomeTransformation(x) #x // stringize the argument
APPLY_TO_ALL(SomeTransformation, 1, 2, 3) // expands to "1" "2" "3"
Demo.
With commas:
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#define ID_OP(_, func, elem) func(elem)
#define APPLY_TO_ALL(func, ...) \
BOOST_PP_SEQ_ENUM( \
BOOST_PP_SEQ_TRANSFORM( \
ID_OP, func, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \
))
// example call:
APPLY_TO_ALL(SomeTransformation, 1, 2, 3) // expands to "1", "2", "3"
Demo.
Check the preprocessor output with g++ -std=c++11 -E -P file.

Assuming you need a PP solution, you can use BOOST_PP_REPEAT:
//invoke IDENTITY_FOR_ALL_MACRO with each index and the given tuple
#define IDENTITY_FOR_ALL(...) \
BOOST_PP_REPEAT( \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
IDENTITY_FOR_ALL_MACRO, \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \
)
//use the index to access the right element of the passed tuple
#define IDENTITY_FOR_ALL_MACRO(z, n, data) \
IDENTITY(BOOST_PP_TUPLE_ELEM(n, data))
IDENTITY_FOR_ALL(abc, 123, "woopee")
//translated to abc 123 "woopee"
It would be decently straightforward to turn this into a more general macro that takes a macro to invoke and the list of single arguments to pass one by one if you need to do this with several different macros and not just IDENTITY.
I'm not 100% sure what you mean by an arbitrary number of arguments, but if you want to invoke IDENTITY with two arguments at a time instead of one, you can change the bottom macro to use BOOST_PP_MUL and BOOST_PP_INC to access the "2n"th and "2n+1"th elements of the tuple, and then invoke the macro only half as many times in the REPEAT call.

Related

How to implement a standard-compliant assert macro with an optional formatted message?

What's the way to implement a standard-compliant assert macro with an optional formatted message?
What I have works in clang, but (correctly) triggers the -Wgnu-zero-variadic-macro-arguments warning if it is turned on (e.g. via -Wpedantic) when the macro is used without the optional message. Wandbox
#define MyAssert(expression, ...) \
do { \
if(!(expression)) \
{ \
printf("Assertion error: " #expression " | " __VA_ARGS__); \
abort(); \
} \
} while(0)
One needs to really use the preprocessor to the max in order to differentiate no additional arguments from the case where they are present. But with Boost.PP one can do this:
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/logical/bool.hpp>
#include <boost/preprocessor/cat.hpp>
#define MyAssert(...) BOOST_PP_CAT(MY_ASSERT,BOOST_PP_BOOL(BOOST_PP_SUB(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1)))(__VA_ARGS__)
#define MY_ASSERT0(expr) MY_ASSERT1(expr,)
#define MY_ASSERT1(expression, ...) \
do { \
if(!(expression)) \
{ \
std::printf("Assertion error: " #expression " | " __VA_ARGS__); \
std::abort(); \
} \
} while(0)
MyAssert must accept at least one argument (standard). Then we count the arguments, subtract one, and turn to a boolean (0 or 1). This 0 or 1 is concatenated to the token MY_ASSERT to form a macro name, to which we proceed to forward the arguments.
MY_ASSERT1 (with args), is your original macro. MY_ASSERT0 substitutes itself with MY_ASSERT1(expr,), the trailing comma means we pass another argument (thus fulfilling the requirement for the one extra argument), but it is an empty token sequence, so it does nothing.
You can see it live.
Since we already went down this rabbit hole, if one doesn't want to pull in Boost.PP the above can be accomplished with the usual argument counting trick, slightly adapted. First, we must decide on a maximum limit for the arguments we allow. I chose 20, you can choose more. We'll need the typical CONCAT macro, and this macro here:
#define HAS_ARGS(...) HAS_ARGS_(__VA_ARGS__,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,)
#define HAS_ARGS_(a1,a2,a3,a4,a5,b1,b2,b3,b4,b5,c1,c2,c3,c4,c5,d1,d2,d3,d4,d5,e, N, ...) N
It's argument counting, but with a twist. When __VA_ARGS__ is a single argument (no extra ones), the N resolved as 0. Otherwise, it is resolved as 1. There can be up to 20 extra arguments after the expression, any number of which will resolve to the same 1. Now we just plug it into the same place we used boost before:
#define MyAssert(...) CONCAT(MY_ASSERT, HAS_ARGS(__VA_ARGS__))(__VA_ARGS__)
You can tinker with it here
I have a solution which I'm not particularly proud of..
We can obtain the first argument in plain form and as a string using:
#define VA_ARGS_HEAD(N, ...) N
#define VA_ARGS_HEAD_STR(N, ...) #N
Note that in usage, in order to not get warnings, you should do VA_ARGS_HEAD(__VA_ARGS__, ) (with the extra ,) so that VA_ARGS_HEAD is never used with a single parameter (trick taken from StoryTeller's answer).
We define the following helper function:
#include <stdarg.h>
#include <stdio.h>
inline int assertionMessage(bool, const char *fmt, ...)
{
int r;
va_list ap;
va_start(ap, fmt);
r = vprintf(fmt, ap);
va_end(ap);
return r;
}
When the assertion has a format string, the function would work with __VA_ARGS__ as is, however when the bool is the only argument, we're missing a format string. That's why we'll add another empty string after __VA_ARGS__ when invoking it:
#define MyAssert(...) \
do { \
if(!(VA_ARGS_HEAD(__VA_ARGS__, ))) \
{ \
printf("Assertion error: %s | ", VA_ARGS_HEAD_STR(__VA_ARGS__, )); \
assertionMessage(__VA_ARGS__, ""); \
abort(); \
} \
} while(0)
Note that assertionMessage doesn't have printf in its name. This is deliberate and intended to avoid the compiler giving format-string related warnings for its invocations with the extra "" argument. The down-side for this is that we don't get the format-string related warnings when they are helpful.
The basic solution is to use << on cerr:
#define MyAssert(expression, msg) \
do { \
if(!(expression)) \
{ \
std::cerr << msg; \
abort(); \
} \
} while(0)
This solution uses C++ streams, so you can format the output as you see fit. Actually this is a simplification of a C++17 solution that I'm using to avoid temporaries (people tend to use + instead of << with this solution, triggering some efficiency warnings).
Use it then like this:
MyAssert(true, "message " << variable << " units");
I think the optionality is bogus here, as you are outputting "Assertion error:" meaning that you expect a message.

Ignoring MACRO argument [duplicate]

Is there some way of getting optional parameters with C++ Macros? Some sort of overloading would be nice too.
Here's one way to do it. It uses the list of arguments twice, first to form the name of the helper macro, and then to pass the arguments to that helper macro. It uses a standard trick to count the number of arguments to a macro.
enum
{
plain = 0,
bold = 1,
italic = 2
};
void PrintString(const char* message, int size, int style)
{
}
#define PRINT_STRING_1_ARGS(message) PrintString(message, 0, 0)
#define PRINT_STRING_2_ARGS(message, size) PrintString(message, size, 0)
#define PRINT_STRING_3_ARGS(message, size, style) PrintString(message, size, style)
#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
#define PRINT_STRING_MACRO_CHOOSER(...) \
GET_4TH_ARG(__VA_ARGS__, PRINT_STRING_3_ARGS, \
PRINT_STRING_2_ARGS, PRINT_STRING_1_ARGS, )
#define PRINT_STRING(...) PRINT_STRING_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
int main(int argc, char * const argv[])
{
PRINT_STRING("Hello, World!");
PRINT_STRING("Hello, World!", 18);
PRINT_STRING("Hello, World!", 18, bold);
return 0;
}
This makes it easier for the caller of the macro, but not the writer.
With great respect to Derek Ledbetter for his answer — and with apologies for reviving an old question.
Getting an understanding of what it was doing and picking up elsewhere on the ability to preceed the __VA_ARGS__ with ## allowed me to come up with a variation...
// The multiple macros that you would need anyway [as per: Crazy Eddie]
#define XXX_0() <code for no arguments>
#define XXX_1(A) <code for one argument>
#define XXX_2(A,B) <code for two arguments>
#define XXX_3(A,B,C) <code for three arguments>
#define XXX_4(A,B,C,D) <code for four arguments>
// The interim macro that simply strips the excess and ends up with the required macro
#define XXX_X(x,A,B,C,D,FUNC, ...) FUNC
// The macro that the programmer uses
#define XXX(...) XXX_X(,##__VA_ARGS__,\
XXX_4(__VA_ARGS__),\
XXX_3(__VA_ARGS__),\
XXX_2(__VA_ARGS__),\
XXX_1(__VA_ARGS__),\
XXX_0(__VA_ARGS__)\
)
For non-experts like me who stumble upon the answer, but can't quite see how it works, I'll step through the actual processing, starting with the following code...
XXX();
XXX(1);
XXX(1,2);
XXX(1,2,3);
XXX(1,2,3,4);
XXX(1,2,3,4,5); // Not actually valid, but included to show the process
Becomes...
XXX_X(, XXX_4(), XXX_3(), XXX_2(), XXX_1(), XXX_0() );
XXX_X(, 1, XXX_4(1), XXX_3(1), XXX_2(1), XXX_1(1), XXX_0(1) );
XXX_X(, 1, 2, XXX_4(1,2), XXX_3(1,2), XXX_2(1,2), XXX_1(1,2), XXX_0(1,2) );
XXX_X(, 1, 2, 3, XXX_4(1,2,3), XXX_3(1,2,3), XXX_2(1,2,3), XXX_1(1,2,3), XXX_0(1,2,3) );
XXX_X(, 1, 2, 3, 4, XXX_4(1,2,3,4), XXX_3(1,2,3,4), XXX_2(1,2,3,4), XXX_1(1,2,3,4), XXX_0(1,2,3,4) );
XXX_X(, 1, 2, 3, 4, 5, XXX_4(1,2,3,4,5), XXX_3(1,2,3,4,5), XXX_2(1,2,3,4,5), XXX_1(1,2,3,4,5), XXX_0(1,2,3,4,5) );
Which becomes just the sixth argument...
XXX_0();
XXX_1(1);
XXX_2(1,2);
XXX_3(1,2,3);
XXX_4(1,2,3,4);
5;
PS: Remove the #define for XXX_0 to get a compile error [ie: if a no-argument option is not allowed].
PPS: Would be nice to have the invalid situations (eg: 5) be something that gives a clearer compilation error to the programmer!
PPPS: I'm not an expert, so I'm very happy to hear comments (good, bad or other)!
With greatest respect to Derek Ledbetter, David Sorkovsky, Syphorlate for their answers, together with the ingenious method to detect empty macro arguments by Jens Gustedt at
https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
finally I come out with something that incorporates all the tricks, so that the solution
Uses only standard C99 macros to achieve function overloading, no GCC/CLANG/MSVC extension involved (i.e., comma swallowing by the specific expression , ##__VA_ARGS__ for GCC/CLANG, and implicit swallowing by ##__VA_ARGS__ for MSVC). So feel free to pass the missing --std=c99 to your compiler if you wish =)
Works for zero argument, as well as unlimited number of arguments, if you expand it further to suit your needs
Works reasonably cross-platform, at least tested for
GNU/Linux + GCC (GCC 4.9.2 on CentOS 7.0 x86_64)
GNU/Linux + CLANG/LLVM, (CLANG/LLVM 3.5.0 on CentOS 7.0 x86_64)
OS X + Xcode, (XCode 6.1.1 on OS X Yosemite 10.10.1)
Windows + Visual Studio, (Visual Studio 2013 Update 4 on Windows 7 SP1 64 bits)
For the lazies, just skip to the very last of this post to copy the source. Below is the detailed explanation, which hopefully helps and inspires all people looking for the general __VA_ARGS__ solutions like me. =)
Here's how it goes. First define the user-visible overloaded "function", I named it create, and the related actual function definition realCreate, and the macro definitions with different number of arguments CREATE_2, CREATE_1, CREATE_0, as shown below:
#define create(...) MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
void realCreate(int x, int y)
{
printf("(%d, %d)\n", x, y);
}
#define CREATE_2(x, y) realCreate(x, y)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_0() CREATE_1(0)
The MACRO_CHOOSER(__VA_ARGS__) part ultimately resolves to the macro definition names, and the second (__VA_ARGS__) part comprises their parameter lists. So a user's call to create(10) resolves to CREATE_1(10), the CREATE_1 part comes from MACRO_CHOOSER(__VA_ARGS__), and the (10) part comes from the second (__VA_ARGS__).
The MACRO_CHOOSER uses the trick that, if __VA_ARGS__ is empty, the following expression is concatenated into a valid macro call by the preprocessor:
NO_ARG_EXPANDER __VA_ARGS__ () // simply shrinks to NO_ARG_EXPANDER()
Ingeniusly, we can define this resulting macro call as
#define NO_ARG_EXPANDER() ,,CREATE_0
Note the two commas, they are explained soon. The next useful macro is
#define MACRO_CHOOSER(...) CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER __VA_ARGS__ ())
so the calls of
create();
create(10);
create(20, 20);
are actually expanded to
CHOOSE_FROM_ARG_COUNT(,,CREATE_0)();
CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER 10 ())(10);
CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER 20, 20 ())(20, 20);
As the macro name suggests, we are to count number of arguments later. Here comes another trick: the preprocessor only does simple text replacement. It infers the number of arguments of a macro call merely from the number of commas it sees inside the parentheses. The actual "arguments" separated by commas need not to be of valid syntax. They can be any text. That's to say, in the above example, NO_ARG_EXPANDER 10 () is counted as 1 argument for the middle call. NO_ARG_EXPANDER 20 and 20 () are counted as 2 arguments for the bottom call respectively.
If we use the following helper macros to further expand them
##define CHOOSE_FROM_ARG_COUNT(...) \
FUNC_RECOMPOSER((__VA_ARGS__, CREATE_2, CREATE_1, ))
#define FUNC_RECOMPOSER(argsWithParentheses) \
FUNC_CHOOSER argsWithParentheses
The trailing , after CREATE_1 is a work-around for GCC/CLANG, suppressing a (false positive) error saying that ISO C99 requires rest arguments to be used when passing -pedantic to your compiler. The FUNC_RECOMPOSER is a work-around for MSVC, or it can not count number of arguments (i.e., commas) inside the parentheses of macro calls correctly. The results are further resolved to
FUNC_CHOOSER (,,CREATE_0, CREATE_2, CREATE_1, )();
FUNC_CHOOSER (NO_ARG_EXPANDER 10 (), CREATE_2, CREATE_1, )(10);
FUNC_CHOOSER (NO_ARG_EXPANDER 20, 20 (), CREATE_2, CREATE_1, )(20, 20);
As the eagle-eyed you may have seen, the last only step we need is to employ a standard argument counting trick to finally pick the wanted macro version names:
#define FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
which resolves the results to
CREATE_0();
CREATE_1(10);
CREATE_2(20, 20);
and certainly gives us the desired, actual function calls:
realCreate(0, 0);
realCreate(10, 10);
realCreate(20, 20);
Putting all together, with some rearrangement of statements for better readability, the whole source of the 2-argument example is here:
#include <stdio.h>
void realCreate(int x, int y)
{
printf("(%d, %d)\n", x, y);
}
#define CREATE_2(x, y) realCreate(x, y)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_0() CREATE_1(0)
#define FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(...) FUNC_RECOMPOSER((__VA_ARGS__, CREATE_2, CREATE_1, ))
#define NO_ARG_EXPANDER() ,,CREATE_0
#define MACRO_CHOOSER(...) CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER __VA_ARGS__ ())
#define create(...) MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
int main()
{
create();
create(10);
create(20, 20);
//create(30, 30, 30); // Compilation error
return 0;
}
Although complicated, ugly, burdening the API developer, there comes a solution for overloading and setting optional parameters of C/C++ functions to us crazy people. The usage of the out-coming overloaded APIs become very enjoyable and pleasant. =)
If there is any further possible simplification of this approach, please do let me know at
https://github.com/jason-deng/C99FunctionOverload
Again special thanks to all of the brilliant people that inspired and led me to achieve this piece of work! =)
C++ macros haven't changed from C. Since C didn't have overloading and default arguments for functions, it certainly didn't have them for macros. So to answer your question: no, those features don't exist for macros. Your only option is to define multiple macros with different names (or not use macros at all).
As a sidenote: In C++ it's generally considered good practice to move away from macros as much as possible. If you need features like this, there's a good chance you're overusing macros.
For anyone painfully searching some VA_NARGS solution that works with Visual C++. Following macro worked for me flawlessly(also with zero parameters!) in visual c++ express 2010:
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,N,...) N
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NARGS(...) bool(#__VA_ARGS__) ? (VA_NUM_ARGS_IMPL_((__VA_ARGS__, 24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1))) : 0
If you want a macro with optional parameters you can do:
//macro selection(vc++)
#define SELMACRO_IMPL(_1,_2,_3, N,...) N
#define SELMACRO_IMPL_(tuple) SELMACRO_IMPL tuple
#define mymacro1(var1) var1
#define mymacro2(var1,var2) var2*var1
#define mymacro3(var1,var2,var3) var1*var2*var3
#define mymacro(...) SELMACRO_IMPL_((__VA_ARGS__, mymacro3(__VA_ARGS__), mymacro2(__VA_ARGS__), mymacro1(__VA_ARGS__)))
That worked for me aswell in vc. But it doesn't work for zero parameters.
int x=99;
x=mymacro(2);//2
x=mymacro(2,2);//4
x=mymacro(2,2,2);//8
gcc/g++ supports varargs macros but I don't think this is standard, so use it at your own risk.
More concise version of Derek Ledbetter's code:
enum
{
plain = 0,
bold = 1,
italic = 2
};
void PrintString(const char* message = NULL, int size = 0, int style = 0)
{
}
#define PRINT_STRING(...) PrintString(__VA_ARGS__)
int main(int argc, char * const argv[])
{
PRINT_STRING("Hello, World!");
PRINT_STRING("Hello, World!", 18);
PRINT_STRING("Hello, World!", 18, bold);
return 0;
}
#include <stdio.h>
#define PP_NARG(...) \
PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#define PP_CONCAT(a,b) PP_CONCAT_(a,b)
#define PP_CONCAT_(a,b) a ## b
#define THINK(...) PP_CONCAT(THINK_, PP_NARG(__VA_ARGS__))(__VA_ARGS__)
#define THINK_0() THINK_1("sector zz9 plural z alpha")
#define THINK_1(location) THINK_2(location, 42)
#define THINK_2(location,answer) THINK_3(location, answer, "deep thought")
#define THINK_3(location,answer,computer) \
printf ("The answer is %d. This was calculated by %s, and a computer to figure out what this"
" actually means will be build in %s\n", (answer), (computer), (location))
int
main (int argc, char *argv[])
{
THINK (); /* On compilers other than GCC you have to call with least one non-default argument */
}
DISCLAIMER: Mostly harmless.
As a big fan of horrible macro monsters, I wanted to expand on Jason Deng's answer and make it actually usable. (For better or worse.) The original is not very nice to use because you need to modify the big alphabet soup every time you want to make a new macro and it's even worse if you need different amount of arguments.
So I made a version with these features:
0 argument case works
1 to 16 arguments without any modifications to the messy part
Easy to write more macro functions
Tested in gcc 10, clang 9, Visual Studio 2017
Currently I just made 16 argument maximum, but if you need more (really now? you're just getting silly...) you can edit FUNC_CHOOSER and CHOOSE_FROM_ARG_COUNT, then add some commas to NO_ARG_EXPANDER.
Please see Jason Deng's excellent answer for more details on the implementation, but I'll just put the code here:
#include <stdio.h>
void realCreate(int x, int y)
{
printf("(%d, %d)\n", x, y);
}
// This part you put in some library header:
#define FUNC_CHOOSER(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, ...) _f16
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(F, ...) FUNC_RECOMPOSER((__VA_ARGS__, \
F##_16, F##_15, F##_14, F##_13, F##_12, F##_11, F##_10, F##_9, F##_8,\
F##_7, F##_6, F##_5, F##_4, F##_3, F##_2, F##_1, ))
#define NO_ARG_EXPANDER(FUNC) ,,,,,,,,,,,,,,,,FUNC ## _0
#define MACRO_CHOOSER(FUNC, ...) CHOOSE_FROM_ARG_COUNT(FUNC, NO_ARG_EXPANDER __VA_ARGS__ (FUNC))
#define MULTI_MACRO(FUNC, ...) MACRO_CHOOSER(FUNC, __VA_ARGS__)(__VA_ARGS__)
// When you need to make a macro with default arguments, use this:
#define create(...) MULTI_MACRO(CREATE, __VA_ARGS__)
#define CREATE_0() CREATE_1(0)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_2(x, y) \
do { \
/* put whatever code you want in the last macro */ \
realCreate(x, y); \
} while(0)
int main()
{
create();
create(10);
create(20, 20);
//create(30, 30, 30); // Compilation error
return 0;
}
That's not really what the preprocessor is designed for.
That said, if you want to enter into the area of seriously challenging macro programming with a modicum of readability, you should take a look at the Boost preprocessor library. After all, it wouldn't be C++ if there weren't three completely Turing compatible levels of programming (preprocessor, template metaprogramming, and base level C++)!
#define MY_MACRO_3(X,Y,Z) ...
#define MY_MACRO_2(X,Y) MY_MACRO(X,Y,5)
#define MY_MACRO_1(X) MY_MACRO(X,42,5)
You know at the point of call how many args you're going to pass in so there's really no need for overloading.
You can use BOOST_PP_OVERLOAD from a boost library.
Example from official boost doc:
#include <boost/preprocessor/facilities/overload.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#define MACRO_1(number) MACRO_2(number,10)
#define MACRO_2(number1,number2) BOOST_PP_ADD(number1,number2)
#if !BOOST_PP_VARIADICS_MSVC
#define MACRO_ADD_NUMBERS(...) BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__)
#else
// or for Visual C++
#define MACRO_ADD_NUMBERS(...) \
BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY())
#endif
MACRO_ADD_NUMBERS(5) // output is 15
MACRO_ADD_NUMBERS(3,6) // output is 9
Depending on what you need, you could do it with var args with macros. Now, optional parameters or macro overloading, there is no such thing.
Not directly answering the question, but using the same trick as David Sorkovsky answer and giving a clear example of how to build complex macros.
Just compile this with g++ -E test.cpp -o test && cat test:
// #define GET_FIRST_ARG_0_ARGS(default) (default)
// #define GET_FIRST_ARG_1_ARGS(default, a) (a)
// #define GET_FIRST_ARG_2_ARGS(default, a, b) (a)
// #define GET_FIRST_ARG_3_ARGS(default, a, b, c) (a)
// #define GET_FIRST_ARG_4_ARGS(default, a, b, c, d) (a)
#define GET_FIRST_ARG_MACROS(default, a, b, c, d, macro, ...) macro
#define GET_FIRST_ARG(default, ...) GET_FIRST_ARG_MACROS( \
,##__VA_ARGS__, \
GET_FIRST_ARG_4_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_3_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_2_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_1_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_0_ARGS(default, ##__VA_ARGS__), \
)
"0,"; GET_FIRST_ARG(0);
"0,1"; GET_FIRST_ARG(0,1);
"0,1,2"; GET_FIRST_ARG(0,1,2);
"0,1,2,3"; GET_FIRST_ARG(0,1,2,3);
"0,1,2,3,4"; GET_FIRST_ARG(0,1,2,3,4);
To see the output:
# 1 "test.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/x86_64-linux-gnu/include/stdc-predef.h" 1 3
# 1 "<command-line>" 2
# 1 "test.cpp"
# 16 "test.cpp"
"0,"; GET_FIRST_ARG_0_ARGS(0);
"0,1"; GET_FIRST_ARG_1_ARGS(0, 1);
"0,1,2"; GET_FIRST_ARG_2_ARGS(0, 1,2);
"0,1,2,3"; GET_FIRST_ARG_3_ARGS(0, 1,2,3);
"0,1,2,3,4"; GET_FIRST_ARG_4_ARGS(0, 1,2,3,4);
Now, a full working program would be:
#include <iostream>
#define GET_FIRST_ARG_0_ARGS(default) (default)
#define GET_FIRST_ARG_1_ARGS(default, a) (a)
#define GET_FIRST_ARG_2_ARGS(default, a, b) (a)
#define GET_FIRST_ARG_3_ARGS(default, a, b, c) (a)
#define GET_FIRST_ARG_4_ARGS(default, a, b, c, d) (a)
#define GET_FIRST_ARG_MACROS(default, a, b, c, d, macro, ...) macro
#define GET_FIRST_ARG(default, ...) GET_FIRST_ARG_MACROS( \
,##__VA_ARGS__, \
GET_FIRST_ARG_4_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_3_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_2_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_1_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_0_ARGS(default, ##__VA_ARGS__), \
)
int main(int argc, char const *argv[]) {
"0,"; GET_FIRST_ARG(0);
"0,1"; GET_FIRST_ARG(0,1);
"0,1,2"; GET_FIRST_ARG(0,1,2);
"0,1,2,3"; GET_FIRST_ARG(0,1,2,3);
"0,1,2,3,4"; GET_FIRST_ARG(0,1,2,3,4);
std::cerr << "0, == " << GET_FIRST_ARG(0) << std::endl;
std::cerr << "0,1 == " << GET_FIRST_ARG(0,1) << std::endl;
std::cerr << "0,1,2 == " << GET_FIRST_ARG(0,1,2) << std::endl;
std::cerr << "0,1,2,3 == " << GET_FIRST_ARG(0,1,2,3) << std::endl;
std::cerr << "0,1,2,3,4 == " << GET_FIRST_ARG(0,1,2,3,4) << std::endl;
return 0;
}
Which would output the following by being compiled with g++ test.cpp -o test && ./test:
0, == 0
0,1 == 1
0,1,2 == 1
0,1,2,3 == 1
0,1,2,3,4 == 1
Note: It is important to use () around the macro contents as #define GET_FIRST_ARG_1_ARGS(default, a) (a) to not break in ambiguous expressions when a is just not a integer.
Extra macro for second argument:
#define GET_SECOND_ARG_0_ARGS(default) (default)
#define GET_SECOND_ARG_1_ARGS(default, a) (default)
#define GET_SECOND_ARG_2_ARGS(default, a, b) (b)
#define GET_SECOND_ARG_3_ARGS(default, a, b, c) (b)
#define GET_SECOND_ARG_4_ARGS(default, a, b, c, d) (b)
#define GET_SECOND_ARG_MACROS(default, a, b, c, d, macro, ...) macro
#define GET_SECOND_ARG(default, ...) GET_SECOND_ARG_MACROS( \
,##__VA_ARGS__, \
GET_SECOND_ARG_4_ARGS(default, __VA_ARGS__), \
GET_SECOND_ARG_3_ARGS(default, __VA_ARGS__), \
GET_SECOND_ARG_2_ARGS(default, __VA_ARGS__), \
GET_SECOND_ARG_1_ARGS(default, __VA_ARGS__), \
GET_SECOND_ARG_0_ARGS(default, ##__VA_ARGS__), \
)
None of the above examples (from Derek Ledbetter, David Sorkovsky, and Joe D) to count arguments with macros worked for me using Microsoft VCC 10. The __VA_ARGS__ argument is always considered as a single argument (token-izing it with ## or not), so the argument shifting in which those examples rely doesn't work.
So, short answer, as stated by many others above: no, you can't overload macros or use optional arguments on them.

How can I get the name of the macro-function?

I have the macro:
#define MYMACRO(pred, ...) \
pred /* here 'pred' is 'mypred(1, 2)', but I need to get only the name without args */
Which is used like this:
MYMACRO(mypred(1, 2))
I need to get only the name of the macro-function, without arguments.
I can do it like this:
#define mypred(...) \
mypred
#define MYMACRO_EXPAND(pred) \
pred /* here 'pred' is 'mypred' without args */
#define MYMACRO(pred, ...) \
MYMACRO_EXPAND(pred)
But this way is bad because I should define the macros for all possible macro-functions.
Ideas?
You could do it like this, but i do not recommend.
For example print the function name.
#define MYMACRO(func, ...) \
(printf("%s\n", #func), func(__VA_ARGS__))
And use it this way
MYMACRO(mypred, 1, 2);
or
int a = MYMACRO(pred, 1, 2);

How do I expand a macro containing commas inside a BOOST_PP_IF

I asked the following question earlier, but the solution doesn't seem to work in this particular case.
How do I print out a comma multiple times using Boost Preprocessor
I am trying to expand a macro containing a comma conditionally. Here is an example illustrating the problem:
#define TEST(...)\
BOOST_PP_REPEAT( \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
MACRO, \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))
#define MACRO(z, n, data) BOOST_PP_IF(1,MACRO_CONTAINING_COMMA(z, z),MACRO_CONTAINING_COMMA(z, z))
#define MACRO_CONTAINING_COMMA(_NAME, _NAME2) _NAME TIBRA_EATEN_COMMA() _NAME2
#define EATEN_COMMA BOOST_PP_IF(1,BOOST_PP_COMMA,BOOST_PP_TUPLE_EAT())
TEST(1,2,3,4)
This expands to
BOOST_PP_IIF BOOST_PP_IIF BOOST_PP_IIF BOOST_PP_IIF
When it should expand to
0,0 1,1 2,2 3,3
You can delay invoking your macro by first selecting it and then invoking it:
#define TEST(...)\
BOOST_PP_REPEAT( \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
MACRO, \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))
#define MACRO(z, n, data) BOOST_PP_IF(1,MACRO_CONTAINING_COMMA,MACRO_CONTAINING_COMMA)(n, n)
#define MACRO_CONTAINING_COMMA(_NAME, _NAME2) _NAME EATEN_COMMA _NAME2
#define EATEN_COMMA BOOST_PP_IF(1,BOOST_PP_COMMA,BOOST_PP_TUPLE_EAT())()
See it work
The IF invocation expands to either your macro without an invocation or something that discard arguments when invoked. After one is chosen, the last parentheses invoke it with the desired arguments without the commas getting in the way.
Apart from that, I changed z to n and TIBRA_EATEN_COMMA() to EATEN_COMMA. As some parts are redundant, you can find a simpler version here.
It turns out that you can do this without __VA_ARGS__. In this simple example I used a comma which is in the template argument of function toString<int,int>() Working demo:
#include <boost/lexical_cast.hpp>
#include <boost/preprocessor.hpp>
#include <iostream>
#include <string>
#define SEQUENCE (1)(2)(3)(4)(5)(6)(7)(8)(9)(10)
#define IGNORE_ARG(arg)
#define GET_NAME(data) BOOST_PP_SEQ_ELEM(0, data)
#define GET_BELOW(data) BOOST_PP_SEQ_ELEM(1, data)
#define PARSE_SEQUENCE(r, data, elem) \
BOOST_PP_IF( \
BOOST_PP_GREATER_EQUAL(elem, GET_BELOW(data)), \
GET_NAME(data), IGNORE_ARG) \
(elem)
#define SKIP_NUMBERS_BELOW(name, below) \
BOOST_PP_SEQ_FOR_EACH(PARSE_SEQUENCE, (name)(below), SEQUENCE)
#define TEST(name) SKIP_NUMBERS_BELOW(name, 4)
#define MACRO_CONTAINING_COMMA(N) toString<N, 2 * N>() <<
template <int a, int b> // whatever, I just need a comma here.
std::string toString() {
return boost::lexical_cast<std::string>(a) + ":" + boost::lexical_cast<std::string>(b) + " ";
}
int main() {
std::cout << TEST(MACRO_CONTAINING_COMMA) "\n";
}

C++ Preprocessor macro loop __VA_ARGS__ 1 vs 2+ arguments

I'm using the macros from this post looping through my arguments. Everything works great! However, is there a way to combine these two CCB_CREATE and CCB_CREATE_MORE?
I need to extract the first argument object_type to write additional code. The additional object_types will be using the FOR_EACH loop to insert into the map.
The compiler complaints when I only have one argument when using CCB_CREATE_MORE(Type1). To fix that I made another macro to handle that CCB_CREATE(Type1). Hoping to find a clever solution to combine these two into one elegant macro. Any ideas?
#define INSERT_LOADER_MAP(object_type) loader_map.insert(make_pair(#object_type, object_type##Loader::loader()))
#define CCB_CREATE_MORE(object_type,...) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
FOR_EACH(INSERT_LOADER_MAP,object_type,__VA_ARGS__); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
#define CCB_CREATE(object_type) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
INSERT_LOADER_MAP(object_type); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
The compiler is likely complaining about the trailing comma when the variadic arguments list is empty. GCC and Visual Studio compilers support the non-standard extension ##__VA_ARGS__ to suppress the trailing comma:
#define FOO(fmt, ...) printf(fmt, ##__VA_ARGS__)
The Visual Studio compilers will also suppress the trailing comma even without the ## extension.
See GCC documentation here, and Visual Studio documentation here.
If you need a standards-compliant solution, there is one detailed in an answer to this question.
So if you are using either gcc or Visual Studio, you should be able to use your original macro with this simple change:
#define CCB_CREATE(object_type,...) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
FOR_EACH(INSERT_LOADER_MAP,object_type,##__VA_ARGS__); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
Edit:
You would need to use the ##__VA_ARGS__ extension in the FOR_EACH() macro as well, or the more elegant modification suggested by ugoren.
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, ##__VA_ARGS__), what, x, __VA_ARGS__)
In addition to Chris Olsen's suggestion, a slight change to the FOR_EACH macro is needed:
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
As a result, FOR_EACH(X, a) will become X(a) (instead of X(a); X();). This eliminates an empty INSERT_LOADER_MAP invocation.