建议把代码复制到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));;
//于是 宏函数实现了和函数一样 完美的 默认参数 可缺省参数
}