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

时间:2015-03-07 22:57:17

标签: c++ c-preprocessor

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

FUNC()或FUNC(1)都应该有效。

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

Func()应映射到do_something_different。

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

请注意,它们是不同的陈述

3 个答案:

答案 0 :(得分:4)

这对于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 ++。

答案 1 :(得分:3)

Variadic宏在类似的情况下可能会有所帮助,但是对于这个特定的例子你并不需要它们(事实上can't use them),因为它不涉及可变数量的参数但只涉及不断变化的性质一个参数的注意事项(请注意,不存在的令牌可以是一个有效的宏参数,用于多种用途,包括此参数)。

如果您提前知道所有表单(或者如果您不关心某些表单不会导致进一步的扩展),您可以使用##运算符发送参数:

#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)

##连接两个令牌以形成一个令牌,然后再进行重新扩展,这样您就可以使用它来根据参数修改宏名称,从而扩展到不同的输出。允许以这种方式使用空参数,方便。

根据你想要实现的其他目标,有很多方法可以使这个变得更复杂,参数数量和扩展阶段不同等等。

e.g。检测 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)

这也演示了##的一个怪癖,它是在扩展其操作数之前粘贴的,所以如果你想扩展和粘贴它需要一个帮助宏。另一方面,空括号被检测为包含不可见参数的事实意味着我们依靠##来检测它们。

将宏用于非常重要的事情可能会非常复杂。 (我不是在宽恕这种风格的使用。)

答案 2 :(得分:1)

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); }