带有函数重载的变分宏

Variadic macros with function overloading

本文关键字:重载 函数      更新时间:2023-10-16

我有一个函数:

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个给定"。有什么想法吗?

您需要做的是更改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)

使用可变模板(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);
}

演示