我遇到过下面用C ++编写的这个函数。使用任意数量的参数调用函数trace()
会以格式
name1:value1 | name2:value2等等。
我想了解这段代码是如何工作的,以及双括号&&
,__VA_ARGS__
等语法的含义。谢谢!
#define tr(...) trace(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void trace(const char* name, Arg1&& arg1){
cout << name << " : " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void trace(const char* names, Arg1&& arg1, Args&&... args){
const char* comma = strchr(names + 1, ',');
cout.write(names, comma-names) << " : " << arg1 << " | " ;
trace(comma+1, args...);
}
答案 0 :(得分:5)
PRCConfiguration
是一个接受可变数量参数的函数宏 它转发stringified版本作为第一个参数 没有使用预处理器就无法派生字符串表示。
评估示例:
#define tr(...) trace(#__VA_ARGS__, __VA_ARGS__)
解析为:
int main(){
int i;
float f;
std::string s;
tr(i,f,s);
}
两个可变参数模板函数展开每个参数并以递归方式调用自身。
结束递归的基本案例函数是:
int main(){
int i;
float f;
std::string s;
trace("i,f,s", i,f,s);
}
使用fold expression可以更干净地完成此操作。
&安培;&安培;用于允许完美转发。
答案 1 :(得分:0)
此功能取决于几种机制:
template <typename Arg1, typename... Args>
其中Arg1
是第一个参数,Args
是其余的。因此函数本身的递归定义 - 解包参数,它自己调用参数列表的尾部。注意comma-names
技巧来计算参数名称的长度。__VA_ARGS__
当然只是tr(...)
(逗号分隔)参数列表的宏。在它之前添加#
是从中创建字符串的内容,它作为trace(const char* names, ...)
中的第一个参数传递。