Not sure if the following is possible in C++20 after a long and exhaustive search but asking anyway:
Using C++20 instead of C's va_list
, can I:
(1) Encode arbitrary argument lists passed to a variadic function template into a single variable so that (2) this variable can be passed to a different, non-templated function where it is (3) decoded and ultimately consumed by a printf()
-like function?
That is, I would like to be able to write something similar to:
/*
* main.cpp
*/
#include <very_old_library.h>
#include <utility>
typedef /*** what goes here? ***/ AmazingVariadicArgumentEncoderType;
/* Impl26() is NOT templated and accepts a FIXED number of arguments */
void Impl26(const char *fmt, AmazingVariadicArgumentEncoderType encodedArgs)
{
/*
* Decode encodedArgs here and represent them as decodedArgs (maybe?)
*/
VeryOldLibraryFunctionWithPrintfSemantics(fmt, decodedArgs... /* not sure what syntax to use for decodedArgs here */);
}
template <typename... Args>
void Wrapper(const char *fmt, Args&&... args)
{
AmazingVariadicArgumentEncoderType encodedArgs;
encodedArgs =
/*
* Encode args here and represent them as encodedArgs.
*
* Possibly using:
* std::forward<Args>(args) ...
* ?
*/
Impl26(fmt, encodedArgs);
}
int main(int argc, char *argv[])
{
// Each of these is a valid invocation of Wrapper().
Wrapper(kOpaqueSecretString1, -123);
Wrapper(kOpaqueSecretString2, "jenny", 8675309, 'q', argv[1]);
Wrapper(kOpaqueSecretString3);
return 0;
}
/*
* very_old_library.h
*/
const char *kOpaqueSecretString1;
const char *kOpaqueSecretString2;
const char *kOpaqueSecretString3;
void VeryOldLibraryFunctionWithPrintfSemantics(const char *fmt, ...);
(The above code is, of course, a distilled version of the real problem I'm trying to solve.)
I'm struggling to find a suitable definition for AmazingVariadicArgumentEncoderType
and the steps to encode to / decode from it.
Restating my question for clarity (thanks @Nelfeal):
Q: How do I write a non-template function that accepts a single parameter and passes it to something like printf()
as multiple arguments?
Here are things which I expect people will suggest which will not work for me:
Use
std::format
and/orstd::iostream
/std::cout
I'm not actually printing to
stdout
. My code specifically interfaces with a library that exposes aprintf()
-like API which uses C-style var args and that library can't be replaced.Make
Impl26()
a function template.In my real code,
Impl26()
is a virtual member function and therefore cannot be templated.#include <stdarg.h>
.I know I could use old C-style varargs in my new code, too, but I'd like to see whether it's possible to avoid doing so. This is as much an experiment and a learning exercise as it is a real problem I'm trying to solve.
Encode as a
std::tuple
.I can't think of a way to pass a
tuple
of arbitrary variables of arbitrary types without makingImpl26()
a function template.Re-implement the format string parsing logic of
printf()
-like functions.I would like a direct pass-through and not try to guess the implementation details of the underlying library.