Introduction
Think macros are simple, boring and of little use, huh?
Background
C++ templates are not a replacement to the C macros, but rather combined together creates a powerful instrument, which allow experienced programmers to implement interesting idioms like Execute Member Function If It Is Present.
Using the Code
So, what we can do with macros?
-
Multi line
#define MIN_(A, B) (\
(A) < (B) ? \
(A) : (B)\
)
-
Variadic
#define PRINT_ERROR_(...) fprintf(stderr, __VA_ARGS__)
-
Concatenation
As strings:
#define HELLO_ "say hello to my little"
#define SPACE_ " "
#define WORLD_ "friend"
static auto const HELLO_WORLD_ = HELLO_""SPACE_""WORLD_;
As tokens:
#define NUMBER_FROM_DIGITS_(D1, D2, D3) D1 ## D2 ## D3
static const auto MY_NUMBER_ = NUMBER_FROM_DIGITS_(1, 2, 3);
-
Stringification
#define MAKE_STR_(STR1, STR2, STR3) #STR1""#STR2""#STR3
static auto const MY_STR_ = MAKE_STR_(paint, _it_, black);
-
Call other
#define M_S_(arg) #arg // stringify
#define MAKE_STR__(arg) M_S_(arg)
static auto const MY_STR__ = MAKE_STR__(INT_MAX);
-
Function-like AND recursion
int f() throw() {return 1;}
#define f() (f() + 1) // self-reference is NOT considered a macro call (passed unchanged)
static const auto VAL_1_ = f();
static auto const VAL_2_ = f;
-
One definition rule
#define SUM(A, B) ((A) + (B))
#define SUM(A, B) ((A) + (B)) // NO compile error here [the rule doesn't applied to macros]
#define SUM(A, B) ((A)+(B)) // compile warning here (allowed redefinition)
#define SUM(A, B) ( (A) + (B) )
#define SUM(A, B) ( (A ) +
( B) ) #define SUM(A, B) ( (A ) /*what if*/ +
( B) )
-
Redefinition "on the fly"
#define SUM(A, B) ((A) + (B))
static const auto VAL_ = SUM(1
#undef SUM
#define SUM + 3
SUM, 2);
Tests
Test code in the Ideone online compiler
std::cout << MIN_(1 + 2, 3 + 4) << std::endl; PRINT_ERROR_("%s they be stealin my %s!", "oh noes", "bucket"); std::cout << HELLO_WORLD_ << std::endl; std::cout << MY_NUMBER_ + 1 << std::endl; std::cout << MY_STR_ << std::endl; std::cout << MY_STR__ << std::endl; std::cout << VAL_1_ << std::endl; std::cout << VAL_2_ + 10 << std::endl; std::cout << VAL_ << std::endl;
Points of Interest
Warning! The result may vary due to the compiler used!
Know more
magic? Share in the comments!
History
- 5th March, 2016: Initial version