宏魔法






4.24/5 (6投票s)
你一直想知道关于宏的一切,但又害怕去问
引言
认为宏很简单、枯燥且用处不大,是吗?
背景
C++ 模板 并非 C 宏 的替代品,而是两者结合起来才能创造出强大的工具,让经验丰富的程序员实现有趣的惯用语,例如 如果成员函数存在则执行它。
Using the Code
那么,我们能用宏做什么?
-
多行
// Literally equal to the #define MIN_(A, B) ((A) < (B) ? (A) : (B)) #define MIN_(A, B) (\ (A) < (B) ? \ (A) : (B)\ )
-
可变参数
// Using PRINT_ERROR_("%s they be stealin my %s!", "oh noes", "bucket") // will print "oh noes they be stealin my bucket" in to the standard error stream #define PRINT_ERROR_(...) fprintf(stderr, __VA_ARGS__)
-
串联
作为字符串
#define HELLO_ "say hello to my little" #define SPACE_ " " #define WORLD_ "friend" // Will be ptr. to the compile-time constant C str. "say hello to my little friend" static auto const HELLO_WORLD_ = HELLO_""SPACE_""WORLD_;
作为标记
#define NUMBER_FROM_DIGITS_(D1, D2, D3) D1 ## D2 ## D3 static const auto MY_NUMBER_ = NUMBER_FROM_DIGITS_(1, 2, 3); // will be 123
-
字符串化
#define MAKE_STR_(STR1, STR2, STR3) #STR1""#STR2""#STR3 // Will be ptr. to the compile-time constant C str. "paint_it_black" static auto const MY_STR_ = MAKE_STR_(paint, _it_, black);
-
调用其他宏
#define M_S_(arg) #arg // stringify #define MAKE_STR__(arg) M_S_(arg) // Will be ptr. to the compile-time constant C str. // In MS VS 2013: "+2,147,483,647" (for 32 bit) // In modern GCC: "INT_MAX" static auto const MY_STR__ = MAKE_STR__(INT_MAX);
-
函数式 AND 递归
int f() throw() {return 1;} // Only expanded if appears with parentheses #define f() (f() + 1) // self-reference is NOT considered a macro call (passed unchanged) static const auto VAL_1_ = f(); // will be 2 static auto const VAL_2_ = f; // will ptr. to the function
-
唯一定义规则
#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) ) // NO compile warning here (if spacers, their amount is ignored) #define SUM(A, B) ( (A ) /*what if*/ + /*add some comments here*/ ( B) ) // NO redefinition here: comments count as spacers
-
“即时”重新定义
#define SUM(A, B) ((A) + (B)) // Will be 1 + 3 + 2 = 6 static const auto VAL_ = SUM(1 #undef SUM #define SUM + 3 SUM, // new definition is used for argument pre-expansion 2); // original definition is used for argument replacement
测试
std::cout << MIN_(1 + 2, 3 + 4) << std::endl; // prints "3"
PRINT_ERROR_("%s they be stealin my %s!", "oh noes", "bucket"); // "oh noes they be stealin my bucket!"
std::cout << HELLO_WORLD_ << std::endl; // "say hello to my little friend"
std::cout << MY_NUMBER_ + 1 << std::endl; // prints 124
std::cout << MY_STR_ << std::endl; // prints "paint_it_black"
std::cout << MY_STR__ << std::endl; // prints "INT_MAX"
std::cout << VAL_1_ << std::endl; // prints "2"
std::cout << VAL_2_ + 10 << std::endl; // prints "1" (as a non-nil pointer)
std::cout << VAL_ << std::endl; // prints "6"
关注点
警告!结果可能因使用的编译器而异!
知道更多
魔法吗?在评论中分享!
历史
- 2016年3月5日:初始版本