【问题标题】:Variadic macros with function overloading具有函数重载的可变参数宏
【发布时间】:2015-12-10 09:26:12
【问题描述】:

我有一个函数:

SendMsg(int x, string y, ...) { /*some code*/ }

我有一个宏:

FOO(X, STRING, ...) SendMsg(X, STRING "%s %d", ##__VA_ARGS__, "xyz", 123)

所以我可以有这样的东西:

FOO(1000, "Note that line %d containing %d words is invalid", 5, 10);

扩展到

SendMsg(1000, "Note that line %d containing %d words is invalid" "%s %d", 5, 10, "xyz", 123);

有时我会遇到这样的事情:

FOO(1000, "String without variables");

应该扩展为

SendMsg(1000, "String without variables" "%s %d", "xyz", 123)

到目前为止,宏运行良好。

但有时我会遇到这样的情况:

FOO(1000);

应该扩展为

SendMsg(1000, "%s "%d", "xyz", 123);

但这不起作用。我收到“宏 FOO 需要 3 个参数,但只给出 1 个参数”的错误。 有什么想法吗?

【问题讨论】:

  • 你不能将空字符串作为第二个参数传递给宏吗?
  • 我想避免这样做。或者引入另一个可以做到这一点的宏。
  • 在这种情况下,宏只能包含第一个参数作为固定参数。从第 2 开始,所有这些都是可变参数。因此,在宏本身中,您可以分别提取宏的第二个参数并将其作为 SendMsg 的第二个参数传递。而函数的第三个参数将是“%s %d”,然后是所有剩余的可变参数+“xyz”+ 123。
  • 如何提取第二个参数?以及如何获得所有剩余的可变参数?

标签: c++ macros overloading variadic-functions variadic-macros


【解决方案1】:

您需要做的是更改 SendMsg 的签名。

SendMsg(int x, char *secondFmt, char *xyx, int no123, ...)
{
     // Print the string in buffer with ##__VA_ARGS__ using sprintf. first 
     // argument extracted from will be string only. otherwise sprintf will fail
     va_start(args, no123);
     const char *fmt = va_arg(args, const char *);
     bytesWrote = sprintf(buffer, fmt, args);
     sprintf(buffer + bytesWrote, secondFmt, xyz, no123);
     va_end(args);
}

现在 Foo 看起来像

FOO(X, ...) SendMsg(X, "%s %d", "xyz", 123, ##__VA_ARGS__)

我所做的是首先打印来自##__VA_ARGS__ 的消息,然后是"%s %d" 部分。以相反的顺序将参数提供给 SendMsg。未经测试,所以只需调整代码。

如果您不想修改 SendMsg,请查看以下代码是否有效。

 FOO(X, ...) {\
  va_start(args, no123);\
  const char *fmt = va_arg(args, const char *);\
  SendMsg(X, fmt "%s %d", "xyz", 123, args);\
  va_end(args);\
}\

如果没有,就写两个宏,:

FOO_FMT(X, STRING, ...) SendMsg(X, STRING"%s %d", "xyz", 123, ##__VA_ARGS__)
FOO(X) SendMsg(X, "%s %d", "xyz", 123)

【讨论】:

  • 不,我不想修改 SendMsg。我也有条件宏扩展。我可能会也可能不会通过 123。
  • 看看其他两种方法是否可行。如果没有,我想我无法为您提供更多帮助。
【解决方案2】:

使用可变参数模板 (C++11),您可以进行重载,例如:

template <typename... Ts>
void FOO(int x, const std::string& format, Ts... args)
{
    SendMsg(x, format + "%s %d", args..., "xyz", 123);
}

void FOO(int x)
{
    SendMsg(x, "%s %d", "xyz", 123);
}

Demo

【讨论】:

    猜你喜欢
    • 2019-01-03
    • 2011-07-14
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    相关资源
    最近更新 更多