经过漫长而详尽的搜索后,不确定以下内容在 C++20 中是否可能,但无论如何还是要问:
使用 C++20 代替 C 的
va_list
,我可以:
(1) 将传递给可变参数函数模板的任意参数列表编码为单个变量,以便 (2) 该变量可以传递给不同的非模板化函数,并在其中进行 (3) 解码并最终被类似 printf()
的函数消耗?
也就是说,我希望能够写出类似的东西:
/*
* 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, ...);
(当然,上面的代码是我试图解决的实际问题的精炼版本。)
我正在努力寻找
AmazingVariadicArgumentEncoderType
的合适定义以及对其进行编码/解码的步骤。
为了清楚起见重申我的问题(感谢@Nelfeal):
问:如何编写一个接受单个参数并将其作为多个参数传递给类似
printf()
的非模板函数?
以下是我希望人们提出的建议,但对我来说不起作用:
使用
std::format
和/或 std::iostream
/std::cout
我实际上并没有打印到
stdout
。我的代码专门与一个库进行交互,该库公开了类似 printf()
的 API,该 API 使用 C 风格的 var args,并且该库无法替换。
制作
Impl26()
函数模板。
在我的真实代码中,
Impl26()
是一个虚拟成员函数,因此无法模板化。
#include <stdarg.h>
。
我知道我也可以在新代码中使用旧的 C 风格可变参数,但我想看看是否可以避免这样做。这既是一个实验和学习练习,也是我试图解决的一个实际问题。
编码为
std::tuple
。
我想不出一种方法可以在不使
tuple
成为函数模板的情况下传递任意类型的任意变量 Impl26()
。
重新实现
printf()
类函数的格式字符串解析逻辑。
我想要直接传递,而不是尝试猜测底层库的实现细节。
使用
std::function
在模板参数已知的上下文中调用 VeryOldLibraryFunctionWithPrintfSemantics
:
/*
* main.cpp
*/
#include <very_old_library.h>
#include <utility>
#include <functional>
using AmazingVariadicArgumentEncoderType = std::function<void(char const*)>;
void Impl26(const char *fmt, AmazingVariadicArgumentEncoderType encodedArgs) {
encodedArgs(fmt);
}
template <typename... Args>
void Wrapper(const char *fmt, Args&&... args) {
AmazingVariadicArgumentEncoderType encodedArgs = [&](char const* fmt) {
VeryOldLibraryFunctionWithPrintfSemantics(fmt, 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;
}