Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C+中的逗号+;宏_C++_C_Macros_C Preprocessor - Fatal编程技术网

C++ C/C+中的逗号+;宏

C++ C/C+中的逗号+;宏,c++,c,macros,c-preprocessor,C++,C,Macros,C Preprocessor,假设我们有一个这样的宏 #define FOO(type,name) type name 我们可以像这样使用它 FOO(int, int_var); 但并非总是如此简单: FOO(std::map<int, int>, map_var); // error: macro "FOO" passed 3 arguments, but takes just 2 FOO(std::map,map_var);//错误:宏“FOO”传递了3个参数,但只接受2个 当然,我们可以做到: t

假设我们有一个这样的宏

#define FOO(type,name) type name
我们可以像这样使用它

FOO(int, int_var);
但并非总是如此简单:

FOO(std::map<int, int>, map_var); // error: macro "FOO" passed 3 arguments, but takes just 2
FOO(std::map,map_var);//错误:宏“FOO”传递了3个参数,但只接受2个
当然,我们可以做到:

 typedef std::map<int, int> map_int_int_t;
 FOO(map_int_int_t, map_var); // OK
typedef std::map-map\u-int\t;
FOO(map_int_int_t,map_var);//好啊

这不是很符合人体工程学。此外,还必须处理类型不兼容问题。知道如何用宏解决这个问题吗?

如果预处理器支持可变宏:

#define SINGLE_ARG(...) __VA_ARGS__
#define FOO(type,name) type name

FOO(SINGLE_ARG(std::map<int, int>), map_var);
#定义单个参数(…)u VA_参数__
#定义FOO(类型、名称)类型名称
FOO(单参数(标准::映射),映射变量);
否则,它就有点乏味了:

#define SINGLE_ARG2(A,B) A,B
#define SINGLE_ARG3(A,B,C) A,B,C
// as many as you'll need

FOO(SINGLE_ARG2(std::map<int, int>), map_var);
#定义单个_ARG2(A,B)A,B
#定义单个参数ARG3(A、B、C)A、B、C
//你需要多少就有多少
FOO(单参数ARG2(标准::映射),映射变量);

至少有两种方法可以做到这一点。首先,可以定义接受多个参数的宏:

#define FOO2(type1, type2, name) type1, type2, name
如果这样做,您可能会发现最终定义了更多宏来处理更多参数

其次,可以在参数周围加括号:

#define FOO(type, name) type name
F00((std::map<int, int>) map_var;
#定义FOO(类型、名称)类型名称
F00((标准::映射)映射变量;

如果您这样做,您可能会发现额外的括号会破坏结果的语法。

简单的答案是您不能。这是为模板参数选择
的一个副作用;
也出现在不平衡的上下文中,因此宏机制无法扩展以处理它们处理括号。(一些委员会成员主张使用不同的标记,例如
(^…^)
,但他们无法使用

说服大多数问题,因为尖括号也可以表示(或出现在)比较运算符
=
,宏展开不能像在括号内一样忽略尖括号内的逗号。(这也是方括号和大括号的问题,即使它们通常以平衡对出现。)可以将宏参数括在括号内:

FOO((std::map<int, int>), map_var);
当然,在C语言中,这是不必要的,因为类型名不能在括号外包含逗号。因此,对于跨语言宏,您可以编写:

#ifdef __cplusplus__
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
#else
#define FOO(t,name) t name
#endif
\ifdef\uuucplusplus__
模板结构参数类型;
模板结构参数_type{typedef U type;};
#定义FOO(t,name)参数\u type::type name
#否则
#定义FOO(t,name)t name
#恩迪夫
这可以通过以下方式实现:


上面的代码只有效地去除了参数列表中的最后一个逗号。请使用
clang-E
(P99需要C99编译器)。

如果您不能使用括号,并且不喜欢Mike的单参数解决方案,请定义一个逗号:

#define COMMA ,

FOO(std::map<int COMMA int>, map_var);
#定义逗号,
FOO(std::map,map_-var);
这也有助于您将某些宏参数字符串化,如中所示

#include <cstdio>
#include <map>
#include <typeinfo>

#define STRV(...) #__VA_ARGS__
#define COMMA ,
#define FOO(type, bar) bar(STRV(type) \
    " has typeid name \"%s\"", typeid(type).name())

int main()
{
    FOO(std::map<int COMMA int>, std::printf);
}
#包括
#包括
#包括
#定义STRV(…)#uuu VA_u参数__
#定义逗号,
#定义FOO(类型,条形)条形(STRV(类型)\
“具有typeid名称\%s\”,typeid(type).name()
int main()
{
FOO(标准::map,标准::printf);
}

它打印的std::map的typeid名称为“st3mapiiist4lessiiesaist4pairikieee”只需将
FOO
定义为

#define UNPACK( ... ) __VA_ARGS__

#define FOO( type, name ) UNPACK type name
然后总是在类型参数周围用括号调用它,例如

FOO( (std::map<int, int>), map_var );
FOO((std::map),map\u-var);

当然,在注释宏定义中,引用调用当然是一个好主意。

我猜你必须从字义中解脱出来,使它们成为文字。至少在C++中,你可以把任何一个TyPyf放置在任何地方,所以我不知道你为什么说它必须是“预先”。.哦,天哪…为什么?为什么不把它括在括号里?@VladLazarenko:因为你不能总是把任意的代码放在括号里。特别是,你不能把括号放在声明符中的类型名称周围,这正是这个参数变成的样子……而且还因为你可能只能修改宏定义,而不能全部修改他把它称为(可能不在你的控制之下,或者可能分布在1000多个文件中,等等)。例如,当添加一个宏以接管类似命名函数的职责时,就会出现这种情况。对于第一种解决方案,每个宏都必须具有不同的名称,因为宏不会重载。对于第二种解决方案,如果您要传递类型名,则很可能会使用它来声明变量(或typedef),所以括号会引起问题。#定义逗号哇,你刚刚为我节省了几个小时的工作…为什么我几年前没有想到这一点。感谢分享这个想法。这甚至允许我构建宏,其中设置函数与不同的参数一起计算。加上1horror@kiw如果您
#定义STRVX(…)STRV(uu VA_uargs_uu)
定义STRV(…)#VAARGS59类型将解决此问题。@WilliamCustode我记得,我一直在研究函数类型和函数声明的语法,并参考了最棘手的解析问题,因此我偶然意识到,在该上下文中,冗余括号可能会应用于类型。我在使用模板时发现此方法存在问题。假设我想要的代码是:
templatevoidsomefunc(FOO(std::map)元素){}
如果我在这里应用此解决方案,宏后面的结构将成为依赖类型,并且类型上现在需要typename前缀。您可以添加它,但类型推断已被破坏,因此您现在必须手动列出类型参数以调用函数。我最终使用temple的方法为逗号定义宏。它可能是看起来没那么漂亮,但效果很好。一个小问题
#include <cstdio>
#include <map>
#include <typeinfo>

#define STRV(...) #__VA_ARGS__
#define COMMA ,
#define FOO(type, bar) bar(STRV(type) \
    " has typeid name \"%s\"", typeid(type).name())

int main()
{
    FOO(std::map<int COMMA int>, std::printf);
}
#define UNPACK( ... ) __VA_ARGS__

#define FOO( type, name ) UNPACK type name
FOO( (std::map<int, int>), map_var );