【问题标题】:How to use variable length parameter list with only one reference parameter?如何使用只有一个参考参数的可变长度参数列表?
【发布时间】:2016-06-06 07:26:47
【问题描述】:

最近遇到一个烦人的问题,想定义这样的函数:

std::string my_sprintf(const char* format, ...)
{
    va_list args;
    va_start(args, format);
    ...
}
std::string my_sprintf(const std::string& format, ...)
{
    va_list args;
    va_start(args, format); // error
    ...
}

但是在使用变长参数列表时,似乎参考值不能是最后一个参数。

这是我可以让用户使用 std::string 作为格式字符串的一种方式吗?

也许检测 std::string 并将其转换为 c_str() 的因素或其他东西会起作用,但我不知道如何处理以下可变长度参数列表。

编辑: 我没有使用可变参数模板,因为我在里面使用了 vsprintf。也许避免使用 vsprintf 并使用 std::stringstream 是一种选择?

【问题讨论】:

  • c 不是 c++
  • C++ 制作printf的方法是使用可变参数模板like here
  • 为什么不使用可变参数模板呢?

标签: c++


【解决方案1】:

行为未定义:请参阅 C++ 标准 18.10/3(适用于 C++11 和 C++14)或cppreference.com: Variadic Arguments

基本上,您只能将 C 中可用的类型与 va_start 一起使用,尽管 std::nullptr_t 类型有一个例外。

【讨论】:

  • 它们也被称为 POD Plain Old Dataread this.
  • 我很清楚这是被禁止的,但我只是想问有没有办法这样做。
  • 不适用于va_start,没有。但是没有理由不能使用可变参数模板。或者只是深拷贝字符串。函数的 i/o 阶段将成为瓶颈,而不是深拷贝。
  • @Bathsheba 因为我在里面使用vsprintf,有没有更好的方法来避免使用它?
  • 您应该指出您所指的 C++ 标准:在 C++14 标准中,有关 va_start() 的信息在 18.10/3 中。
【解决方案2】:

在 C++ 中,传递 "unknown" 参数的方式是使用可变参数模板:

template <typename ... Ts>
std::string my_sprintf(const std::string& format, Ts&&...args)
{
    return my_sprintf(format.c_str(), std::forward<Ts>(args)...);
}

您使用const char* 的版本可能也应该是可变参数模板,使用sprintf 而不是vsprintf

【讨论】:

  • @user2079303:使用两个版本的可变参数,它都可以工作Demo。但实际上,使用省略号时,它是模棱两可的,需要进行一些重命名才能解决此问题。
  • @Jarod42 哦,对了。我试图在真空中理解这段代码 - 没有意识到有过载。抱歉吵了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-27
  • 2020-06-05
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
相关资源
最近更新 更多