我想创建将参数插入函数调用的宏。例如,我在下面声明了函数Action()
。 Action接受一个状态编号的枚举和带有字符串可选参数的格式化字符串。
我想定义宏,这样我就可以调用Action( ActionState1, "someText %d", &arg)
而不是使用ActionState1
调用State1("someText %d", &arg)
作为状态参数。这样宏就会在我的状态参数ActionState1
中出现。我正在考虑以下内容:
#define State1(formatedString, ...) Action(ActionState1, formatedString, ...)
#define State2(formatedString, ...) Action(ActionState2, formatedString, ...)
#define State3(formatedString, ...) Action(ActionState3, formatedString, ...)
enum {
ActionState1,
ActionState2,
ActionState3
}
static void Action( State state, String formatedString, ...);
有谁知道这是什么样的格式?
答案 0 :(得分:2)
使用预处理器无法做到这一点。预处理器允许您对实体进行串联,但不能采用相反的方式。根据您的需要,您需要将State1
分解为两个组件State
和1
(后者更重要)并继续进行通话。
然而,更重要的问题是你为什么要这样做?你很难通过这样的转变保存任何打字或获得可读性。
你可以使用模板获取附近的东西:
template <size_t N>
T State(string fmt, ...) { return Action(N, fmt, ...); } // assume T Action(size_t, ...);
并将上述内容用作:
State<1>(fmtStr, ...);
State<2>(fmtStr2, ...);
但同样,IMO几乎没有语法上的好处。
答案 1 :(得分:2)
我相信__VA_ARGS__
正是您所寻找的:
#define State1(formattedString, ...) Action(1, (formattedString), __VA_ARGS__)
.
.
.
这是一个C99功能,Wikipedia claims它们不是任何官方C ++标准的一部分(我注意到这是因为你使用C ++标签),但是一个相当流行的扩展。在this question进行了一些很好的讨论。
答案 2 :(得分:0)
你为什么要创造这样的东西?在C ++中,首先使用流式算子或类似的方法来使用varargs,因为它可以提高类型的安全性。
我不相信有任何方法可以在C ++预处理器宏中执行您想要的操作。如果你有一个va_list版本的Action,你可能会得到类似下面的内容,但我似乎记得...
之前的参数必须是POD - 遗憾的是快速搜索无法确认或否认。
#include <cstdarg>
inline void State1(String formatedString, ...)
{
va_list args;
va_start(args, formatedString);
Action(1, formatedString, args);
va_end(args);
}