CPP {宏定义,可变长宏参数(…与__VA_ARGS__)}
宏定义
性质
#define A( _a, _b) ...
, 对于A( pair<int,int>, ...)
此时他会报错, 因为他没把pair<int,int>
看作成是一个整体;
解决办法是: 加上括号, 即A( (pair<int,int>), ...)
就没问题了;
@DELI;
#宏的参数的逗号问题#
ASSERT_(x)
, 对于ASSERT_( is_same_v< _T, int64_t>);
这会报错 因为他里面有个,
逗号 会认为是(x,y)
;
.
解决办法是: ASSERT_( (is_same_v< _T, int64_t>) );
, 即用一个把他括起来;
@DELI;
宏定义里可以有注释 不影响的, 因为注释会被清除掉;
#define A int a // xx
当你调用A;
时, 他并不是int a // xx;
(这个代码是错误的), 他会变成int a;
錯誤
#二維坐標轉換為一維坐標 #define Trans_( _x, _y) (_x * M + _y)
#
錯誤;
比如Trans_( x+1, y)
, 此時他會變成x + M + y
, 而正確的是(x+1)*M+y
;
這是宏定義非常常見的一個錯誤, 所以推薦 所有宏參數 都加上括號, 即寫成(_x)*M + (_y)
;
但是 最好的處理是: 不要用宏定義來處理運算操作, 你就把他寫成函數把, 效率不會差太多的…
#
性质
#
在宏定義裡的功能是: 字符串化 (即對把參數給帶上引號 從而變成了一個常量字符串)
#define A(x) #x
#define B(...) #__VA_ARGS__
auto a = A(abc); // 等价于`const char * a = "abc"`
auto a = B(abc,123); // 等价于 `const char * a = "abc, 123"` (這是系統的格式 即中間以`, `(逗號+空格)為分割;
##
性质
##
用於 源代碼的拼接;
對於#define A( _pre, _suf)
我們的目的是: 比如對於A( pp, ss)
他要變成int ppXss = 1;
如果你寫成#define A( _pre, _suf) int _pre X _suf = 1;
這會報錯的, 因為他會變成int pp X ss = 1
, 即中間有空格; 如果你把空格去掉 即把宏定義為int _preX_suf = 1
這更是錯誤的 因為參數_pre, _suf
就沒有使用到;
正確的做法是: #define A( _pre, _suf) int _pre##X##_suf = 1;
(也可以寫成_pre ## X ## _suf
), 即##
的作用是拼接, 即對於a ## b ## c
他會變成abc
這是程序源代碼層面上的拼接 即直接對源代碼進行拼接;
.
此時你A( hh, gg)
就對應為int hhXgg = 1
;
再比如: #define A( _pre) _pre ## 10
, 此時A(0x) = 0x10
, A(0b) = 0b10
; 他是純源代碼層面上的拼接;
可变长宏参数(...
与__VA_ARGS__
)
性质
@DELI;
#define D( a, ...) cout<<a; Func(__VA_ARGS__)
這也是可以的;
注意額外的參數a
要放在前面, 即D(..., a)
是錯誤的, ...
的後面 是不可以再有其他參數的 即(..., a)
或(..., ...)
都是錯誤的;
.
此时...
可以为空, 即D( 123)
这是可以的, 则__VA_ARGS_ == 空
, 即Func()
;
@DELI;
可变长宏: #define D_( ...) Func( __VA_ARGS__), cout<< #__VA_ARGS__
;
当你调用D_( "abc", add(1,2))
时, 此时的...
等价于 __VA_ARGS__
等价于"abc", add(1,2)
, 也就是 他有2项 一项是"abc"
一项是add(1,2)
;
.
因此Func( __VA_ARGS__)
就等价于Func( "abc", add(1,2))
, 即 你的Func
函数 必须是形如(const char *, int)
的函数 (当然他也可以是个变长模板函数);
#__VA_ARGS__
为'"abc", add(1,2)'
这个字符串;
@DEIL;
__VA_ARGS__
的對象 不一定是函數, 也可以繼續放到宏裡面
#define EXIT_( ...) DE_( __VA_ARGS__, "EXIT!"), exit(0) // 這裡`...`的內容(即__VA__ARGS__) 繼續放到了`DE_`宏裡面;
#define DE_( ...) Tools::__Debug( __VA_ARGS__)
#ifdef, #if, #elif
性质
#ifdef XX
Do1();
#else
Do_else();
#endif
@DELI;
#if XX == 1
Do1();
#elif XX == 2
Do2();
#else
DO_else();
#endif