my problem with vsprintf
is that I can not obtain input arguments directly, I have to first get inputs one by one and save them in void**
, then pas
Following class works for me:
class VaList
{
va_list _arguments;
public:
explicit inline VaList(const void * pDummy, ...)
{
va_start(_arguments, pDummy);
}
inline operator va_list &()
{
return _arguments;
}
inline operator const va_list &() const
{
return _arguments;
}
inline ~VaList()
{
va_end(_arguments);
}
};
and it can be used like this:
void v(const char * format, const va_list & arguments)
{
vprintf(format, const_cast(arguments));
}
...
v("%d\n", VaList("", 1)); // Uses VaList::operator va_list &()
v("%d %d\n", VaList(nullptr, 2, 3)); // Uses VaList::operator va_list &()
vprintf("%s %s %s\n", VaList("", "Works", "here", "too!"));
const VaList args(NULL, 4, 5, "howdy", "there");
v("%d %d %s %s\n", args); // Uses VaList::operator const va_list &() const
The first dummy parameter can be any kind of pointer, it is only used to compute the address of the following arguments.
The same can of course be done in C too but not so niftily (use pointer instead of reference)!
Simple example of using VaList to construct a dynamic va_list:
static void VectorToVaList(const std::vector & v, va_list & t)
{
switch (v.size())
{
case 1: va_copy(t, VaList("", v[0])); return;
case 2: va_copy(t, VaList("", v[0], v[1])); return;
case 3: va_copy(t, VaList("", v[0], v[1], v[2])); return;
case 4: va_copy(t, VaList("", v[0], v[1], v[2], v[3])); return;
// etc
}
throw std::out_of_range("Out of range vector size!");
}
and usage:
va_list t;
VectorToVaList(std::vector{ 1, 2, 3, 4 }, t);
vprintf("%d %d %d %d\n", t);