函数打印任意数量的参数
C++ Function to print any number of arguments
我遇到了下面这个用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...);
}
#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);
}
两个可变的模板函数展开每个实参并递归地调用自己。
结束递归的基case函数为:
template <typename Arg1>
void trace(const char* name, Arg1&& arg1){
cout << name << " : " << arg1 << endl;
}
这可以用折叠表达式更简洁地完成。
,,用于允许完全转发。
这个函数取决于几个机制:
-
可变模板:为了支持任意数量的参数,函数被定义为可变模板。这个特性具有递归语法,就像您在函数式语言中遇到的那样:
template <typename Arg1, typename... Args>
,其中Arg1
是第一个参数,Args
是所有其他参数。因此函数本身的递归定义—为了解压缩形参,它调用自己作为实参列表的尾部部分。注意comma-names
技巧计算参数名的长度。 -
预处理字符串化操作符:
__VA_ARGS__
当然只是tr(...)
参数列表的宏(逗号分隔)。在它之前添加#
是创建字符串的原因,它作为trace(const char* names, ...)
的第一个参数传递。 - 引用崩溃 (Arg&&在模板中):这实际上是这里最复杂的东西,这很遗憾,因为它几乎什么都不做。您可以直接删除&&s,代码仍然可以像预期的那样工作。什么,,它调整预期参数的引用类型以匹配实际传递的内容,例如,如果你通过引用传递一个参数,它不会复制它,如果你传递一个临时对象,它将使用move语义。这个特性的实现技术说起来有点痛苦,所以这里有另一个so问题需要进一步阅读
相关文章:
- 在函数中使用 const int size 参数创建数组会在 Visual Studio 中抛出错误 C++:表达式的计
- 如何在模板函数中实例化其长度使用模板参数的数组
- 基于参数创建数组
- Pybind11 默认参数 numpy 数组或 None
- 有没有办法根据命令行参数定义数组大小?运行时与编译时实例化?
- 更改为参数的数组的值
- 根据 C++11 中的模板参数选择数组大小
- 是否可以使用C 函数中的const int参数创建数组
- 根据参数将数组分成 5 个不同的数组
- 你究竟如何通过函数的参数传递数组?
- 函数参数中数组大小未指定
- 数组作为函数参数查找数组长度时出错
- 如何在C++中找到任意数组的大小
- 如何使用函数参数设置数组大小
- 可变参数模板数组调用未定义的行为
- 提升 1.55,而 13 信号参数错误数
- 指向作为模板参数的数组的指针
- C++可变参数模板数组/访问元素
- 在具有任意数量子级的节点树中查找节点
- 在 c++ 中没有参数的数组