这种奇怪的每个实例都与一个常规的单个省略号的情况配对。
template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes...)>
{ typedef _Res result_type; };
template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes......)>
{ typedef _Res result_type; };
template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes...) const>
{ typedef _Res result_type; };
template<typename _Res, typename... _ArgTypes>
struct _Weak_result_type_impl<_Res(_ArgTypes......) const>
{ typedef _Res result_type; };
我的猜测是双省略号在含义上与 _ArgTypes..., ... 相似,即可变参数模板扩展后跟 C 样式的可变参数列表。
Here's a test 支持该理论……我认为我们有一个新的赢家,因为我们是有史以来最差的伪操作员。
编辑:这似乎是一致的。 §8.3.5/3 描述了一种将参数列表形成为的方法
参数声明列表opt ...opt
所以双省略号是由一个以参数包结尾的参数声明列表组成,后跟另一个省略号。
逗号完全是可选的; §8.3.5/4 确实说
在语法正确且“...”不是抽象声明符的一部分的情况下,“, ...”与“...”同义。
这个是在一个抽象声明器中,[edit],但是 Johannes 提出了一个很好的观点,他们指的是参数声明中的一个抽象声明器。我想知道他们为什么不说“参数声明的一部分”,以及为什么这句话不仅仅是一个信息性注释……
此外,<cstdarg> 中的va_begin() 需要在可变参数列表之前有一个参数,因此C++ 专门允许的原型f(...) 是没有用的。与 C99 交叉引用,在普通 C 中是非法的。所以,这是最奇怪的。
使用说明
根据要求,双省略号here is a demonstration:
#include <cstdio>
#include <string>
template< typename T >
T const &printf_helper( T const &x )
{ return x; }
char const *printf_helper( std::string const &x )
{ return x.c_str(); }
template< typename ... Req, typename ... Given >
int wrap_printf( int (*fn)( Req... ... ), Given ... args ) {
return fn( printf_helper( args ) ... );
}
int main() {
wrap_printf( &std::printf, "Hello %s\n", std::string( "world!" ) );
wrap_printf( &std::fprintf, stderr, std::string( "Error %d" ), 5 );
}