是否可以将 va_list 传递给可变参数模板?

And*_*joe 5 c++ templates variadic-functions variadic-templates c++11

我知道这va_list通常是您应该避免的事情,因为它不是很安全,但是是否可以从如下函数传递参数:

void foo(...);
Run Code Online (Sandbox Code Playgroud)

到一个函数

template<typename... Args>
void bar(Args... arguments);
Run Code Online (Sandbox Code Playgroud)

?

编辑:最初我想尝试使用它来调用具有可变数量的参数/类型的虚函数,但这并不是使这个问题变得无关紧要的方法。最终我最终做了这样的事情:

struct ArgsPackBase
{
    virtual ~ArgsPackBase() {}
};

template<typename... Args>
struct ArgsPack : public ArgsPackBase
{
public:
    ArgsPack(Args... args_)
        : argsTuple(args_...)
    {}

    void call(std::function<void(Args...)> function)
    {
        callExpansion(function, std::index_sequence_for<Args...>{});
    }

private:
    template<std::size_t... I>
    void callExpansion(std::function<void(Args...)> function, std::index_sequence<I...>)
    {
        function(std::get<I>(argsTuple)...);
    }

    std::tuple<Args...> argsTuple;
};
Run Code Online (Sandbox Code Playgroud)

小智 5

不,可变参数函数参数是运行时功能,您传递给可变参数模板的参数数量虽然可变,但必须在编译时知道。


max*_*x66 5

正如 RFC1925 中所观察到的,“有了足够的推力,猪就能飞得很好。然而,这不一定是个好主意。”

正如 Piotr Olszewski 所指出的,旧的 C 风格可变参数函数参数是一个旨在在运行时工作的功能;新的可变参数模板 C++ 风格在编译时工作。

所以......只是为了好玩......我想如果你知道编译时间,参数的类型,这是可能的foo()

例如, iffoo()是一个可变参数模板函数,如下foo()例所示...可以使用 clang++ 进行编译和工作,但使用 g++ 会出现编译错误...我不知道谁是对的(当我有时间时,我'将就此提出一个问题)...

#include <cstdarg>
#include <iostream>
#include <stdexcept>

template <typename ... Args>
void bar (Args const & ... args)
 { 
   using unused = int[];

   (void)unused { (std::cout << args << ", ", 0)... };

   std::cout << std::endl;
 }

template <typename ... Ts>
void foo (int num, ...)
 {
   if ( num != sizeof...(Ts) )
      throw std::runtime_error("!");

   va_list args;                     

   va_start(args, num);           

   bar( va_arg(args, Ts)... );

   va_end(args);
 }

int main ()
 {
   foo<int, long, long long>(3, 1, 2L, 3LL); // print 1, 2, 3, 
 }
Run Code Online (Sandbox Code Playgroud)

请注意,您需要传递冗余信息foo():可变参数的数量:语法要求您传递具有相同值的va_start变量 ( ) 。numsizeof...(Ts)

但是,我再说一遍,只是为了好玩。

为什么,看在上帝的份上,我们应该编写一个函数,就像foo()我们可以直接编写这样的函数一样bar()