Recently I meet an annoying problem that I want to define functions like this:
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
...
}
But it seems reference value can't be the last parameter when using variable length parameter list.
Is that a way that I can let user use std::string as format string?
Maybe factors or something else that detect std::string and convert it as c_str() would work, but I don't know how to deal with the following variable length parameter list.
Edit: I'm not using variadic template because i'm using vsprintf inside. Maybe avoid using vsprintf and using std::stringstream is an option?
Non - Keyworded Arguments (args) To provide variable-length parameters, we need to use an asterisk before the parameter name in the given method. The type of parameters supplied is a tuple, and within the method, these passed arguments form a tuple with the same name as the parameter, excluding the asterisk.
The va_list may be passed as an argument to another function, but calling va_arg() within that function causes the va_list to have an indeterminate value in the calling function. As a result, attempting to read variable arguments without reinitializing the va_list can have unexpected behavior.
A variable-length argument is a feature that allows a function to receive any number of arguments. There are situations where a function handles a variable number of arguments according to requirements, such as: Sum of given numbers. Minimum of given numbers and many more.
The behaviour is undefined: See C++ Standard 18.10/3 (for C++11 and C++14), or cppreference.com: Variadic Arguments.
Essentially you can only use types that are available in C with va_start
, although an exception is made for the std::nullptr_t
type.
In C++, the way to pass "unknown" arguments is to use variadic template:
template <typename ... Ts>
std::string my_sprintf(const std::string& format, Ts&&...args)
{
return my_sprintf(format.c_str(), std::forward<Ts>(args)...);
}
and you version with const char*
should probably also be variadic template, by using sprintf
instead of vsprintf
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With