Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.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++中,变量宏至少需要一个参数来表示“…”。考虑函数:FooA,B,…如果我希望这两个呼叫都正确且无警告,我应该怎么做?FOO5,4,gamma;FOO5,4;我使用的是-pedantic标志,所以不能仅仅抑制警告_C++_Macros_Variadic - Fatal编程技术网

可变宏警告 C++中,变量宏至少需要一个参数来表示“…”。考虑函数:FooA,B,…如果我希望这两个呼叫都正确且无警告,我应该怎么做?FOO5,4,gamma;FOO5,4;我使用的是-pedantic标志,所以不能仅仅抑制警告

可变宏警告 C++中,变量宏至少需要一个参数来表示“…”。考虑函数:FooA,B,…如果我希望这两个呼叫都正确且无警告,我应该怎么做?FOO5,4,gamma;FOO5,4;我使用的是-pedantic标志,所以不能仅仅抑制警告,c++,macros,variadic,C++,Macros,Variadic,第二个给出了上面提到的编译时警告。我认为: 将定义更改为FOOa。。。;并拆分代表。。。进入b,如果存在,进入其余。所以函数调用看起来像:FOO5,4gamma;和FOO5,4;我认为,这不是一个好的选择,因为拆分不是有效的,函数声明将不需要b参数,即使它是强制性的 有没有更好的方法获得无警告编译 您可以删除此宏,因为宏是邪恶的,并用模板或其他东西替换它 您可以定义两个宏:FOOs(具有许多参数)和FOO(仅具有两个参数) 假设您使用的是gcc或兼容编译器,则可以使用 您可以删除此宏,因为宏是邪

第二个给出了上面提到的编译时警告。我认为:

将定义更改为FOOa。。。;并拆分代表。。。进入b,如果存在,进入其余。所以函数调用看起来像:FOO5,4gamma;和FOO5,4;我认为,这不是一个好的选择,因为拆分不是有效的,函数声明将不需要b参数,即使它是强制性的

有没有更好的方法获得无警告编译

您可以删除此宏,因为宏是邪恶的,并用模板或其他东西替换它 您可以定义两个宏:FOOs(具有许多参数)和FOO(仅具有两个参数) 假设您使用的是gcc或兼容编译器,则可以使用 您可以删除此宏,因为宏是邪恶的,并用模板或其他东西替换它 您可以定义两个宏:FOOs(具有许多参数)和FOO(仅具有两个参数) 假设您使用的是gcc或兼容编译器,则可以使用
我不理解您的具体问题,但从您所展示的情况来看,使用两个重载函数要容易得多

void foo(int, int);
void foo(int, int, const std::string&);

foo(3, 4); // calls first
foo(3, 4, "hello"); // calls second
甚至可能:

void foo(int, int, const std::string& = "");
另一方面,如果可以使用C++11:

template<typename... Args>
void foo(int, int, const Args&... args); // google variadic templates

参数包args可以由零个或多个参数组成

我不理解您的具体问题,但从您的演示来看,使用两个重载函数要容易得多

void foo(int, int);
void foo(int, int, const std::string&);

foo(3, 4); // calls first
foo(3, 4, "hello"); // calls second
甚至可能:

void foo(int, int, const std::string& = "");
另一方面,如果可以使用C++11:

template<typename... Args>
void foo(int, int, const Args&... args); // google variadic templates

参数包args可以由零个或多个参数组成

虽然我完全同意,如果可能的话,应该使用可变函数或函数模板,但这个问题也表明了对宏可以做什么和不能做什么的一些误解,所以在这个回答中,我将假装函数不是一个选项

将定义更改为FOOa。。。;并拆分代表。。。进入b,如果存在,进入其余

所以函数调用看起来像:FOO5,4gamma;和FOO5,4

否。继续调用FOO5,4,gamma;和FOO5,4;。在第一种情况下,参数是4,gamma。在第二种情况下,参数是4

如果需要从前者中提取gamma,可以由预处理器完成。它要求对参数的数量有一个上限,但您可以将其增加到您喜欢的任何数量。不过很难看

如果_VA_ARGS____)不包含逗号,则提取很简单:

#define COMMA_TRAILING_ARGS_0(a)
如果您知道uu VA_ARGS_uuu至少包含一个逗号,则可以使用

#define COMMA_TRAILING_ARGS_1(a, ...) , __VA_ARGS__
您可以检测要使用哪一个,直到宏参数的某个上限:

#define ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, )
合并:

#define COMMA_TRAILING_ARGS_0(a)
#define COMMA_TRAILING_ARGS_1(a, ...) , __VA_ARGS__

#define ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,)

#define CONCAT(a, b) a ## b
#define CONCAT_(a, b) CONCAT(a, b)

#define FOO(a, ...) BAR(a CONCAT_(COMMA_TRAILING_ARGS_, HAS_COMMA(__VA_ARGS__)) (__VA_ARGS__))

FOO(5, 4, x, q);    // expands to BAR(5, x, q);
FOO(5, 4, "gamma"); // expands to BAR(5, "gamma");
FOO(5, 4);          // expands to BAR(5);

虽然我完全同意,如果可能的话,应该使用可变函数或函数模板,但这个问题也表明了对宏可以做什么和不能做什么的一些误解,所以在这个答案中,我将假装函数不是一个选项

将定义更改为FOOa。。。;并拆分代表。。。进入b,如果存在,进入其余

所以函数调用看起来像:FOO5,4gamma;和FOO5,4

否。继续调用FOO5,4,gamma;和FOO5,4;。在第一种情况下,参数是4,gamma。在第二种情况下,参数是4

如果需要从前者中提取gamma,可以由预处理器完成。它要求对参数的数量有一个上限,但您可以将其增加到您喜欢的任何数量。不过很难看

如果_VA_ARGS____)不包含逗号,则提取很简单:

#define COMMA_TRAILING_ARGS_0(a)
如果您知道uu VA_ARGS_uuu至少包含一个逗号,则可以使用

#define COMMA_TRAILING_ARGS_1(a, ...) , __VA_ARGS__
您可以检测要使用哪一个,直到宏参数的某个上限:

#define ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, )
合并:

#define COMMA_TRAILING_ARGS_0(a)
#define COMMA_TRAILING_ARGS_1(a, ...) , __VA_ARGS__

#define ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,)

#define CONCAT(a, b) a ## b
#define CONCAT_(a, b) CONCAT(a, b)

#define FOO(a, ...) BAR(a CONCAT_(COMMA_TRAILING_ARGS_, HAS_COMMA(__VA_ARGS__)) (__VA_ARGS__))

FOO(5, 4, x, q);    // expands to BAR(5, x, q);
FOO(5, 4, "gamma"); // expands to BAR(5, "gamma");
FOO(5, 4);          // expands to BAR(5);

为什么要使用宏?您要解决的实际问题是什么?可变函数模板是您的解决方案。@DeiDei您能详细介绍一下函数模板吗?为什么要使用宏?你想解决的实际问题是什么?一个可变函数模板就是你的解决方案。@DeiDei你能详细说明一下函数模板吗?但这意味着我必须用FOO5,4;FOOs5,4,gamma;,这和我想要的有点不同,但这意味着我必须吃5,4;FOOs5,4,gamma;,这和我想要的有点不同。