[你绝对没看过的逆天文章]使用__VA_ARGS__和__VA_OPT__实现 宏函数 支持 默认参数 可缺省参数

建议把代码复制到vs观看好看一点,全文都在代码里了

原创不易 请注明出处


#include <iostream>
using namespace std;

//以pl举例
void _pl(std::ostream& os) {
	//GetOs;
	os << endl << "----------" << endl;
}
void _pl(std::ostream& os, int ct) {
	//GetOs;
	os << endl;
	for (int i = 0; i < ct; i++) {
		os << "-";
	}
	os << endl;
}
void _pl(std::ostream& os, string title) {
	//GetOs;
	os << endl << "--[" << title << "]----------" << endl;
}
void _pl(std::ostream& os, string title, int ct) {
	//GetOs;
	os << endl << "--[" << title << "]";
	for (int i = 0; i < ct; i++) {
		os << "-";
	}
	os << endl;
}
void _pl(std::ostream& os, string title, int ct,string tail_1,string tail_2) {
	//GetOs;
	os << endl << "--[" << title << "]";
	for (int i = 0; i < ct; i++) {
		os << "-";
	}
	os << tail_1;
	os << tail_2;
	os << endl;
}


int main()
{
	
//__VA_ARGS__代表前面的...

//初识__VA_ARGS__, 这样写一个宏替代所有重载
#define PL(...) _pl(__VA_ARGS__)
	PL(cout, "你好", 10);
	//展开内联为:
	_pl(cout, "你好", 10);
//如果我想PTL()不写第一参数,并且让他默认是cout(打印大部分的时候用cout,每次都写cout太麻烦)该怎么写
#define PL_1(...) _pl(cout,__VA_ARGS__ )
//这样很好
	PL_1( "你好");
	//展开内联为:
	_pl(cout, "你好");
//但是如果我这样呢
	//PTL_1();//报错了 
	//展开内联为:
	//_ptl(cout, );//发现逗号在碍事,有没有办法去掉呢
//于是c++20有了__VA_OPT__这个东西__VA_OPT__(,)
//在__VA_ARGS__为空的时候也会变成空,在__VA_ARGS__里面有参数的时候就会变成逗号
//当然你要是写成__VA_OPT__(ABC),在__VA_ARGS__里面有参数的时候就会变成ABC
//__VA_OPT__的正确用法如下
//注意 项目-属性-常规-c++语言标准 要设置为c++20或以上
//同时 项目-属性-c++-预处理器-使用标准符合性预处理器 要改成 是(/Zc:preprocessor)
	#define PTL_2(...) _pl(cout __VA_OPT__(,) __VA_ARGS__ )
//问题解决 没有烦人的逗号了
	PTL_2();
	//展开内联为:
	_pl(cout);

//另一个例子

//已有一个宏函数 用于打印参数
#define pv(logTool,logLevel,var)	logTool->logLevel(to_string(var));
//我想要一个方便的打印函数 永远使用LOG4CPLUS库来打印并且可以指定打印级别,不指定的话就默认是DEBUG
//该怎么写 前半部分#define easy_pv(t,...)肯定是对的 后面改怎么写呢,
//这样pv(LOG4CPLUS __VA_OPT__(,) __VA_ARGS__,t)会有一个问题 
//当不写打印级别的时候就变成pv(LOG4CPLUS,t)了,少了一个参数并且参数位置不对
#define easy_pv(t,...) pv(LOG4CPLUS __VA_OPT__(,) __VA_ARGS__,t)
	//easy_pv(123);
	//展开内联为:
	//LOG4CPLUS->123(to_string());;
//该怎么写才能让中间的参数...默认是DEBUG
//既然__VA_OPT__可以实现根据__VA_ARGS__参数数量来消除逗号或者字符串,同样的我们岂不是也可以反向利用他
//如何反向利用:我们先定义两个宏 使用默认参数和不使用默认参数(注意这个Dont)
#define UseDfArg(dfArg) dfArg
#define DontUseDfArg(dfArg) 
//然后我们这样
#define rpv(var,...) pv(LOG4CPLUS , __VA_OPT__(Dont)##UseDfArg(DEBUG)  __VA_ARGS__ , var)	
//利用##拼接字符串 把__VA_OPT__(Dont)当成取反号用 反向利用 达到设置默认参数的目的
	rpv(111);
	//展开内联为:
	pv(LOG4CPLUS, DEBUG, 111);
	
	rpv(222,ERROR);
	//展开内联为:
	pv(LOG4CPLUS, ERROR, 222);
//就问在座的各位 眼前一亮了了有没有 宏函数居然也可以用默认参数!!

//现在我要把它扩展开来 让他支持更多个数的默认参数
#define pv(logTool,logLevel,timestamp,file,func,line,var)	logTool->logLevel(timestamp,file,func,line,to_string(var));
#define rpv1(var,logLevel,timestamp,file,func,...) pv(LOG4CPLUS ,logLevel,timestamp,file,func, __VA_OPT__(Dont)##UseDfArg(1001)  __VA_ARGS__ , var)
	rpv1(333, DEBUG, "[11:11:11]", "a.cpp", "func007");//展开内联为:
	LOG4CPLUS->DEBUG("[11:11:11]", "a.cpp", "func007", 1001, to_string(333));;
#define rpv2(var,logLevel,timestamp,file,...) rpv1(var,logLevel,timestamp,file,__VA_OPT__(Dont)##UseDfArg("func007")  __VA_ARGS__)
	rpv2(333, DEBUG, "[11:11:11]", "a.cpp");//展开内联为:
	LOG4CPLUS->DEBUG("[11:11:11]", "a.cpp", "func007", 1001, to_string(333));;
#define rpv3(var,logLevel,timestamp,...) rpv2(var,logLevel,timestamp,__VA_OPT__(Dont)##UseDfArg("a.cpp")  __VA_ARGS__)
	rpv3(333, DEBUG, "[11:11:11]");//展开内联为:
	LOG4CPLUS->DEBUG("[11:11:11]", "a.cpp", "func007", 1001, to_string(333));;
#define rpv4(var,logLevel,...) rpv3(var,logLevel,__VA_OPT__(Dont)##UseDfArg("[11:11:11]")  __VA_ARGS__)
	rpv4(333, DEBUG);//展开内联为:
	LOG4CPLUS->DEBUG("[11:11:11]", "a.cpp", "func007", 1001, to_string(333));;
#define rpv5(var,...) rpv4(var,__VA_OPT__(Dont)##UseDfArg(DEBUG)  __VA_ARGS__)
	rpv5(333);//展开内联为:
	LOG4CPLUS->DEBUG("[11:11:11]", "a.cpp", "func007", 1001, to_string(333));;
//最后
#define rpv rpv5
//可以用了 随意试下
	rpv(333, ERROR, "[01:22:33]");//展开内联为:
	LOG4CPLUS->ERROR("[01:22:33]", "a.cpp", "func007", 1001, to_string(333));;
	rpv(333, INFO, "[05:08:06]","b.cpp");//展开内联为:
	LOG4CPLUS->INFO("[05:08:06]", "b.cpp", "func007", 1001, to_string(333));;
	rpv(333, INFO, "[05:08:06]","b.cpp","foo",1234);//展开内联为:
	LOG4CPLUS->INFO("[05:08:06]", "b.cpp", "foo", 1234, to_string(333));;

//于是 宏函数实现了和函数一样 完美的 默认参数 可缺省参数

}

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值