C++ 具有 0 或 1 参数的宏

C++ Macro with either 0 or 1 parameter

本文关键字:参数 具有 C++      更新时间:2023-10-16

我想创建一个C++宏,它可以不带任何参数,也可以接受单个参数。

FUNC() 或 FUNC(1) 都应该工作。

我想知道如何使用可变参数宏来实现这一点。

Func() 应该映射到 do_something_different。

Func(1) 应该映射到do_something(1)。

请注意,它们是不同的语句

可变参数宏在类似情况下可能会有所帮助,但对于此特定示例,您不需要它们(实际上也不能使用它们),因为它不涉及可变数量的参数,而只涉及一个参数的更改性质(请注意,不存在的令牌可以成为许多用途的有效宏参数,包括这个)。

如果您

事先知道参数的所有形式(或者如果您不关心某些不会导致进一步扩展),则可以使用 ## 运算符调度参数:

#define FUNC(X) FUNC_IMPL_ ## X
#define FUNC_IMPL_ do_something_different
#define FUNC_IMPL_1 do_something(1)
FUNC()   // -> do_something_different
FUNC(1)  // -> do_something(1)

##将两个标记连接成一个,然后重新扩展,因此您可以使用它根据参数修改宏名称,从而扩展到不同的输出。空参数也允许以这种方式方便地使用。

有很多方法可以使这变得更加复杂,具有不同的参数编号和扩展阶段等,具体取决于您想要实现的其他目标。

例如,检测任何FUNC的参数并将其传递给do_something需要相当多的扩展技巧:

#define ONE_OR_TWO(...) ONE_OR_TWO_(__VA_ARGS__, 2, 1,)
#define ONE_OR_TWO_(_1, _2, X, ...) X
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A ## B
#define FUNC(X) CAT(DO_SOMETHING_, ONE_OR_TWO(FUNC_IMPL_ ## X))(X)
#define FUNC_IMPL_ ,
#define DO_SOMETHING_2(_) do_something_different
#define DO_SOMETHING_1(X) do_something(X)
FUNC()   // -> do_something_different
FUNC(1)  // -> do_something(1)
FUNC(2)  // -> do_something(2)

这也演示了##的一个怪癖,即它在扩展其操作数之前进行粘贴,因此如果要扩展和粘贴,则需要一个辅助宏。另一方面,空括号被检测为包含不可见参数的事实意味着我们必须依靠##来检测它们。

将宏用于任何重要的事情可能非常复杂。(我不容忍使用这种风格。

这对于

C++11个可变参数宏来说是微不足道的

#define FUNC(...) do_something(__VA_ARGS__)

这在 C++11 之前是不可能的,除非作为扩展。

但是,C++使用宏根本不需要(并且会被认为是糟糕的风格,因为它不安全)。 只需将它们作为带有默认参数的函数执行即可。

void FUNC(int x = 0)
{
    do_something(x);
}
FUNC();    // calls FUNC(0)
FUNC(1);

或作为重载函数

void FUNC()
{
    do_something();  // can remove brackets here, although getting it to compile cleanly would be interesting
}
void FUNC(int x)
{
     do_something(x);
}
FUNC();
FUNC(1);

后者确实假定do_something()要么重载,要么具有具有默认值的参数。

这些选项适用于所有版本的C++。

void func(extra) { do_something_different(); }
void func(a, extra) { do_something(a); }
#define FUNC(...) func(__VA_ARGS__, #__VA_ARGS__)

简单:

void func() { do_something_different(); }
void func(a) { do_something(a); }
#define FUNC(...) func(__VA_ARGS__)

您不需要可变参数宏:

void func() { do_something_different(); }
void func(a) { do_something(a); }
#define FUNC func

你甚至根本不需要宏:

void FUNC() { do_something_different(); }
void FUNC(a) { do_something(a); }