如何在各个参数中拆分#__VA_ARGS__
How to split #__VA_ARGS__ in individual parameters
在可变宏中,#__VA_ARGS__
是所有参数的逗号分隔字符串(至少我用gcc和clang得到了这种行为)。有没有一种方法可以在不解析字符串的情况下为各个参数创建一个字符串数组?
我正在使用下面的代码创建调试输出,如
DEBUG DUMP int main() AT demo.cc:53:
atan2(0.5, 0.5) => 0.785398
1 + 2 => 3
1 == 2 => false
来自等代码
debug_dump(atan2(0.5, 0.5), 1 + 2, 1 == 2);
但是,我目前的解决方案使用一个特殊的lexer来分割#__VA_ARGS__
字符串,当然,它无法使用模板参数(如)解析复杂的情况
debug_dump(std::pair<int,int>().first, 0 < 1);
因为没有简单的方法来区分哪个CCD_ 3和/或CCD_。以下是我当前代码(需要C++11)的一个简短的自包含示例:
#include <utility>
#include <stdio.h>
#include <math.h>
void debug_dump_val_worker(int v) { fprintf(stderr, "%d", v); }
void debug_dump_val_worker(bool v) { fprintf(stderr, "%s", v ? "true" : "false"); }
void debug_dump_val_worker(double v) { fprintf(stderr, "%f", v); }
void debug_dump_args_worker(const char *) { }
template <typename T, typename ... Args>
void debug_dump_args_worker(const char *p, T first, Args ... args)
{
int next_p_state = 0;
const char *next_p = p;
while (*next_p && (next_p_state != 0 || *next_p != ',')) {
if (*next_p == '"')
do {
next_p++;
while (*next_p == '' && *(next_p + 1))
next_p += 2;
} while (*next_p && *next_p != '"');
if (*next_p == ''') {
next_p++;
if (*next_p == '')
next_p++;
if (*next_p)
next_p++;
}
if (*next_p == '(' || *next_p == '[' || *next_p == '{')
next_p_state++;
if ((*next_p == ')' || *next_p == ']' || *next_p == '}') && next_p_state > 0)
next_p_state--;
next_p++;
}
fprintf(stderr, "nt%.*s => ", int (next_p - p), p);
if (*next_p == ',')
next_p++;
while (*next_p == ' ' || *next_p == 't' || *next_p == 'r' || *next_p == 'n')
next_p++;
debug_dump_val_worker(first);
debug_dump_args_worker(next_p, args ...);
}
#define debug_dump(...) do {
fprintf(stderr, "DEBUG DUMP %s AT %s:%d:", __PRETTY_FUNCTION__, __FILE__, __LINE__);
debug_dump_args_worker(#__VA_ARGS__, __VA_ARGS__);
fprintf(stderr, "n");
} while (0)
int main()
{
debug_dump(atan2(0.5, 0.5), 1 + 2, 1 == 2);
debug_dump(std::pair<int,int>().first, 0 < 1);
return 0;
}
Yakk说,预处理器不将<>
视为匹配。
因此,如果你要这样做,那么你的代码需要比预处理器"更聪明"。一旦__VA_ARGS__
被扩展到对debug_dump_args_worker
的调用的参数中,就需要整个C++编译器来对其进行排序,并识别出有两个参数,而不是三个。在更复杂的情况下,>>
旨在关闭两个模板参数列表,直到C++11,编译器才必须这样做,而不是将其视为一个不合时宜的移位运算符。因此,事实上,您的代码需要比C++03编译器"更聪明"(也就是说,您需要上下文敏感的标记化)。
我建议你最好的选择是放弃,并要求用户说:
debug_dump((std::pair<int,int>().first), 0 < 1);
相反。这是将模板参数转换为单个宏参数的"常用"方法。您至少可以通过检查从字符串中提取的表达式数量是否等于参数包的长度来捕捉错误。如果用户忘记在模板参数列表周围放置parens,那么您会发现字符串中有太多表达式。
相关文章:
- C++将向量的向量拆分为向量的N个子向量
- 如何拆分文件中.txt字母并使用c ++使用数组进行扑克?
- OpenCV 4.1.2 - 从网络摄像头获取帧并将其拆分
- 使用 C++ 将命令行参数拆分为参数/向量
- C++(.cpp文件和.h文件)拆分代码并添加一个函数,提取 - 这很容易吗?
- 如何在C++中将数字拆分为数字
- 在线程之间拆分任务总是值得的吗?
- 将字符串拆分为标记,并将标记拆分为两个单独的数组
- 在 c++ 中拆分类和标头中的继承,错误
- 在矢量内拆分 deques
- 拆分重叠段
- 我还可以添加什么来按空格或空格正确拆分C++字符串?
- 通过空行提升拆分字符串
- 给定一个大小为 N 的数组 S,检查是否可以将序列拆分为两个序列
- 如何按多个括号类型拆分字符串,但仍将括号保留在C++?
- 将 Boost.Spirit.X3 解析器拆分为多个 TU
- 将字符串拆分为等长 c++ 的部分
- 将执行循环拆分为多个线程 (1-N-1-N-1..)
- 使用范围拆分string_view
- 将 std::大小为 m 的向量拆分为大小为 n 的向量