尝试回复another question,为了好玩,我编写了以下愚蠢的程序,尝试使用新的C ++样式的可变参数模板参数列表转换旧的C风格的可变参数函数参数列表(也在wandbox)
#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,
}
但是clang ++并且没有问题地执行它,g ++给出了以下错误
prog.cc: In function 'void foo(int, ...)':
prog.cc:26:25: error: expansion pattern 'va_arg(args, Ts)' contains no argument packs
bar( va_arg(args, Ts)... );
^~~
像往常一样:谁是对的?
g ++或clang ++?
附录
更改行
bar( va_arg(args, Ts)... );
in
bar( ((void)Ts{}, va_arg(args, Ts))... );
程序由两个编译器编译,但执行它,clang ++版本打印
1, 2, 3,
当g ++版本恢复值并打印时,(如所预期的那样)
3, 2, 1,