学习宏编程
C/C++宏编程的艺术
用括号对封装参数叫元组,展开时移除.
#define 宏删括(T) 宏删括_ T
#define 宏删括_(...) __VA_ARGS__
用宏函数来代替特殊符号,这是懒求值(即尽量先展开再求值).
#define 宏逗() ,
#define 宏左括() (
#define 宏右括() )
#define 宏空的()
先展开,再求值:
#define 宏连(A,B) 宏连_(A,B)
#define 宏连_(A,B) A##B
不然,要出问题.自增/自减逻辑运算,都很简单.
 懒求值很爽,不犯错误:
#define 宏如(判,则,异) 宏连(宏如_,宏极(判))(则,异)
#define 宏逗如(N) 宏如(N,宏逗,宏空的)()
//都是一样的.
相当于()()这种二次函数了.
#define 包围(N) \
    宏如(N,宏左括,[ 宏空的)() N  宏如(N,宏右括,] 宏空的)()
都是尽量懒求值,先展开再求值.
 c++20用__VA_OPT__来处理变长参数展开为空的情况.如__VA_OPT__(,) __VA_ARGS__)表示为空时,则不要这个,号.
#define 福(P,T) 宏如(P,宏几_1,宏几_0) T
福(0,(foo,bar))  // -> foo
福(1,(foo,bar))  // -> bar
福(0,(baz))       // -> baz
同样的懒求值,由于是T是元组所以可以直接连接.
 然后是检查变长参数是否为空.
#define 宏是空(...) \
 宏与(宏与(宏非(宏有逗(__VA_ARGS__)),宏非(宏有逗(__VA_ARGS__()))),宏与(宏非(宏有逗(宏逗值 __VA_ARGS__)),宏有逗(宏逗值 __VA_ARGS__())))
#define 宏有逗(...) 宏几_8(__VA_ARGS__,1,1,1,1,1,1,1,0,0)
#define 宏逗值(...) ,
这里要逗 变参()展开为逗,而变参,变参(),逗 变参均展开为非逗才叫宏是空的.
#define 宏变选逗(...) 宏微软(宏逗如(宏非(宏是空(__VA_ARGS__))))
实现c++20的(,),然后就可实现参数个数:
#define 宏参数(...) \
 宏微软(宏几(8,__VA_ARGS__ 宏变选逗(__VA_ARGS__) 8,7,6,5,4,3,2,1,0))
即变参后面跟着个动态变化的,号.只能用宏几(8,不能用宏几8.后者未展开.前者会展开.与微软__VA_ARGS__一样的道理.
 然后实现每一,这是重点:
#define 宏每一(干,c,...) \
 宏微软(宏连(宏每一_,宏参数(__VA_ARGS__))(干,c,__VA_ARGS__))
#define 宏每一_1(干,c,v,...) 干(c,v) 
#define 宏每一_2(干,c,v,...) \
 干(c,v) 宏微软(宏每一_1(干,c,__VA_ARGS__))
...
这里与原文不一样,人家的有i参数,我这里去掉了.随时都要注意.有__VA_ARGS__,就记得加上宏微软的扩展.不然不行的.
 BOOST_PP提供四种数据结构:元组,序列,列表,数组.
| 结构 | 造型 | 
|---|---|
| 元组 | 都放一个括号里面 | 
| 序列 | 每个元素放一括号 | 
| 列表 | 递归二元组,类似 c++的型列(大神的现代c++设计). | 
| 数组 | (长度,元组),已过时. | 
宏在遇见当前宏是,不会继续展开.因而不支持递归/重入.二维的,比较麻烦.要自己去学习.
 宏当.
#define 宏当 宏当_1
#define 宏当_1(判,操作,值) \
 宏如(判(值),宏当_2,值 宏空值)  (判,操作,宏如(判(值),操作,宏空值)(值))
...
判为判断,可接参数.操作,接收操作,返回下个状态.第3个为状态.有简单的,有复杂的.如:
#define 宏当(f,o,s) 宏当_1(f,o,s) 
#define 宏当_1(f,o,s) 宏如(f(1,s),宏当_2(f,o,o(1,s)),s)
#define 宏当_2(f,o,s) 宏如(f(2,s),宏当_3(f,o,o(2,s)),s)
...
及类似,f/o接2个参数.
#define 宏当 宏当_1
#define 宏当_1(判,操作,值) \
 宏如(判(值),宏当_2,值 宏空值)  (判,操作,宏如(判(值),操作,宏空值)(值))
...
#define 判(值) 宏取几(1,值)
#define 操作(值) \
 (宏取几(0,值) + 宏取几(1,值),宏降(宏取几(1,值)))
上面的,判断/操作接1个参数.即宏当有多种形式.
 还有不带状态的自动推导.不过建议宏当尽量传递状态,这样可以不用自动推导.
 借助宏当,可以实现+-*/%,甚至比较操作.宏编程主要是在非用宏不可的地方,比如定义类.而其他很多都可借用编译时元编程,那里就可以大展伸手了.
 宏毕竟还是带链子跳舞.会宏每一,最多宏当就行啦.
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号