如何通过 #define 函数向格式化字符串函数调用添加参数

发布于 2024-09-17 22:59:40 字数 727 浏览 6 评论 0原文

我想创建将参数插入函数调用的宏。例如,我在下面声明了函数 Action()。 Action 采用状态编号的枚举和带有可选字符串参数的格式化字符串作为输入。

我想定义宏,以便不用使用 ActionState1 作为状态参数调用 Action( ActionState1, "someText %d", &arg) ,我只需调用 < code>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, ...);

有谁知道正确的格式是什么?

I want to create macros that will insert a parameter into a function call. For example, I have function Action() declared below. Action takes as it's inputs an enum for the state number and a formatted string with optional args for the string.

I want to define macros so that instead of callingAction( ActionState1, "someText %d", &arg) with ActionState1 for the state parameter, I can just call State1("someText %d", &arg) instead. That way the macro would stick in the ActionState1 for the state param for me. I'm thinking of something like the following:

#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, ...);

Does anyone know what the proper format for this would be?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瀞厅☆埖开 2024-09-24 22:59:40

我相信 __VA_ARGS__ 是您要查找的内容:

#define State1(formattedString, ...) Action(1, (formattedString), __VA_ARGS__)
 .
 .
 .

这是一项 C99 功能,Wikipedia 声称它们不是任何官方 C++ 标准的一部分(我注意到这一点是因为您使用了 C++ 标签),而是一个相当流行的扩展。 这个问题有一些很好的讨论< /a>.

I believe that __VA_ARGS__ is what you're looking for:

#define State1(formattedString, ...) Action(1, (formattedString), __VA_ARGS__)
 .
 .
 .

This is a C99 feature, and Wikipedia claims that they are not part of any official C++ standard (I note this because you use the C++ tag), but a fairly popular extension. There is some good discussion over at this question.

后来的我们 2024-09-24 22:59:40

不,这不能使用预处理器来完成。预处理器允许您将实体串起来,但不能反向操作。对于您想要的,您需要将 State1 分解为两个组件 State1 (后者更重要),然后继续称呼。

然而,更重要的问题是你为什么要这样做?通过这样的转换,您几乎无法节省任何打字或获得可读性。

不过,您可以使用模板在附近获得一些东西:

template <size_t N> 
T State(string fmt, ...) { return Action(N, fmt, ...); } // assume T Action(size_t, ...);

并将上面的内容用作:

State<1>(fmtStr, ...);
State<2>(fmtStr2, ...);

但同样,IMO 这里几乎没有任何语法增益。

No this cannot be done using the preprocessor. The preprocessor allows you to string up entities but not go the reverse way. For what you want, you will need to break up State1 to two components State and 1 (the latter being more important) and proceed with the call.

However, the more important question is why would you want to do this? You hardly save any typing by such a transformation or gain readability.

You could get something nearby using templates though:

template <size_t N> 
T State(string fmt, ...) { return Action(N, fmt, ...); } // assume T Action(size_t, ...);

and use the above as:

State<1>(fmtStr, ...);
State<2>(fmtStr2, ...);

But again, there's hardly any syntactic gain here IMO.

橘寄 2024-09-24 22:59:40

为什么要创造这样的东西?在 C++ 中,更喜欢使用流运算符或类似的操作符而不是使用可变参数,因为它除其他外还获得了类型安全性。

我不相信有任何方法可以在 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);
}

Why do you want to create such a thing? In C++ Prefer to use streaming operators or similar over using varargs as it gains type safety among other things.

I don't believe there's any way to do what you want in C++ preprocessor macros. If you had a va_list version of Action, you might be able to get away with something like the following, but I seem to recall that the parameter before the ... must be POD - unfortunately a quick search can't confirm or deny that.

#include <cstdarg>
inline void State1(String formatedString, ...)
{
    va_list args;
    va_start(args, formatedString);
    Action(1, formatedString, args);
    va_end(args);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文