提问人:pion 提问时间:7/26/2023 最后编辑:pion 更新时间:7/26/2023 访问量:128
C++20:将参数包编码和解码为变量,供 varargs 使用
C++20: Encode and decode parameter pack as a variable to be used by varargs
问:
不确定在经过长时间和详尽的搜索后,C++ 20 中是否可以进行以下操作,但无论如何都会问:
使用 C++2 而不是 C ,我可以:(1) 将传递给可变参数函数模板的任意参数列表编码为单个变量,以便 (2) 该变量可以传递给不同的非模板化函数,在那里它被 (3) 解码并最终被类似函数使用? va_list
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
我实际上并没有打印到 .我的代码专门与一个库接口,该库公开了一个类似 API 的 API,该 API 使用 C 样式的 var args,并且该库无法替换。
stdout
printf()
将
Impl26()
设为函数模板。在我的实际代码中,是一个虚拟成员函数,因此无法模板化。
Impl26()
#include < stdarg.h>
。我知道我也可以在我的新代码中使用旧的 C 样式变量,但我想看看是否有可能避免这样做。这既是一个实验和学习练习,也是我试图解决的一个真正问题。
编码为
std::tuple
。我想不出一种方法可以在不制作函数模板的情况下传递任意类型的任意变量。
tuple
Impl26()
重新实现类似
printf()
函数的格式字符串解析逻辑。我想要直接传递,而不是试图猜测底层库的实现细节。
答:
用于在已知模板参数的上下文中调用:std::function
VeryOldLibraryFunctionWithPrintfSemantics
/*
* main.cpp
*/
#include <utility>
#include <functional>
using EncoderCallback = void(*)(char const*, ...);
using AmazingVariadicArgumentEncoderType = std::function<void(EncoderCallback, char const*)>;
void Impl26(const char *fmt, AmazingVariadicArgumentEncoderType encodedArgs) {
encodedArgs(VeryOldLibraryFunctionWithPrintfSemantics, fmt);
}
template <typename... Args>
void Wrapper(const char *fmt, Args&&... args) {
AmazingVariadicArgumentEncoderType encodedArgs = [=](EncoderCallback callback, char const* fmt) {
callback(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;
}
评论
printf
fmt
%d
vprintf
),但这只是你列表的第 3 点。AmazingVariadicArgumentEncoderType
va_list