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)
正如 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()?