C++20:将参数包编码和解码为由 varargs 使用的变量

问题描述 投票:0回答:1

经过漫长而详尽的搜索后,不确定以下内容在 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()
的非模板函数?


以下是我希望人们提出的建议,但对我来说不起作用:

  1. 使用

    std::format
    和/或
    std::iostream
    /
    std::cout

    我实际上并没有打印到

    stdout
    。我的代码专门与一个库进行交互,该库公开了类似
    printf()
    的 API,该 API 使用 C 风格的 var args,并且该库无法替换。

  2. 制作

    Impl26()
    函数模板。

    在我的真实代码中,

    Impl26()
    是一个虚拟成员函数,因此无法模板化。

  3. #include <stdarg.h>

    我知道我也可以在新代码中使用旧的 C 风格可变参数,但我想看看是否可以避免这样做。这既是一个实验和学习练习,也是我试图解决的一个实际问题。

  4. 编码为

    std::tuple

    我想不出一种方法可以在不使

    tuple
    成为函数模板的情况下传递任意类型的任意变量
    Impl26()

  5. 重新实现

    printf()
    类函数的格式字符串解析逻辑。

    我想要直接传递,而不是尝试猜测底层库的实现细节。

c++ parameter-passing c++20 variadic-templates variadic-functions
1个回答
0
投票

使用

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.