如何使用只有一个参考参数的可变长度参数列表?
Posted
技术标签:
【中文标题】如何使用只有一个参考参数的可变长度参数列表?【英文标题】: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
为什么不使用可变参数模板呢?
【参考方案1】:
行为未定义:请参阅 C++ 标准 18.10/3(适用于 C++11 和 C++14)或cppreference.com: Variadic Arguments。
基本上,您只能将 C 中可用的类型与 va_start
一起使用,尽管 std::nullptr_t
类型有一个例外。
【讨论】:
它们也被称为 POD Plain Old Data,read 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 哦,对了。我试图在真空中理解这段代码 - 没有意识到有过载。抱歉吵了。以上是关于如何使用只有一个参考参数的可变长度参数列表?的主要内容,如果未能解决你的问题,请参考以下文章
Java 我在学反射的时候,遇到可变长度参数列表,具体的成员方法就是?