Warning, black magic ahead.
Macros can indeed be used, albeit with a preset number of arguments. This number can be arbitrary, but each must be written by hand:
#include <stdio.h> #include <stdlib.h> #define MERGE_EXPAND( a , b ) a##b #define MERGE( a , b ) MERGE_EXPAND( a , b ) #define COUNT_PICK( a , b , c , pick , ... ) pick #define COUNT( ... ) COUNT_PICK( __VA_ARGS__ , 3 , 2 , 1 , 0 ) #define JOIN_1( a ) a #define JOIN_2( a , b ) a##b #define JOIN_3( a , b , c ) a##b##c #define JOIN( ... ) MERGE( JOIN_ , COUNT( __VA_ARGS__ ) )( __VA_ARGS__ ) int main( void ) { printf( "%d\n" , JOIN( 12345 ) ) ; printf( "%d\n" , JOIN( 100,44 ) ) ; printf( "%d\n" , JOIN( -10,44,9999 ) ) ; return EXIT_SUCCESS ; }
The macro COUNT count the number of arguments passed to it. This is done by passing arguments to the helper macro COUNT_PICK, and adding additional argument which are consecutive numbers in reverse order. The number of original arguments passed to COUNT then manipulates the arguments of COUNT_PICK, so that one of the numbers is chosen.
That chosen number is then merged wtih JOIN, resulting in either JOIN_1, JOIN_2, or JOIN_3. The chosen macro is then used with original arguments and simply merges them into a single integer literal.
This example can be expanded by manually defining more JOIN_X macros where X is a consecutive number. Simultaneously the macros COUNT and COUNT_PICK, must be altered as well.
As an additional benefit, passing invalid arguments, like:
JOIN( 10,+44 ); JOIN( 10,-44 ); JOIN( 10,*44 ); JOIN( 10,/44 ); JOIN( /10,44 ); //etc...
will yield a compile time warning, but still allows for arguments that will result in a valid integer constant.
To be used with a Microsoft compiler, tested with SVC14 (Microsoft Visual Studio 2015 Update 3), the code must be amended. Macros COUNT_PICK and MERGE must be wrapped with an additional expand macro:
#define EXPAND(...) __VA_ARGS__
10'000'000in C++14. Won't happen, but wouldn't you want to#undefit afterwards? Or would you avoid writing,for the rest of the file when it should have its normal meaning?10'000'000.#define MAX (10 * 1000 * 1000)