学习宏编程

参考地址

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/o2个参数.

#define 宏当 宏当_1
#define 宏当_1(判,操作,值) \
 宏如(判(值),宏当_2,值 宏空值)  (判,操作,宏如(判(值),操作,宏空值)(值))
...
#define 判(值) 宏取几(1,值)
#define 操作(值) \
 (宏取几(0,值) + 宏取几(1,值),宏降(宏取几(1,值)))

上面的,判断/操作1个参数.即宏当有多种形式.
还有不带状态的自动推导.不过建议宏当尽量传递状态,这样可以不用自动推导.
借助宏当,可以实现+-*/%,甚至比较操作.宏编程主要是在非用宏不可的地方,比如定义类.而其他很多都可借用编译时元编程,那里就可以大展伸手了.
宏毕竟还是带链子跳舞.会宏每一,最多宏当就行啦.

posted @   zjh6  阅读(26)  评论(0编辑  收藏  举报  
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示