What is the meaning of "... ..." token? i.e. double ellipsis operator on parameter pack

在浏览 gcc 当前实现的新 C + + 11头文件时,我偶然发现了“ ... ...”令牌。您可以检查下面的代码 compiles fine[ via Godbolt.org ]。

template <typename T>
struct X
{ /* ... */ };


template <typename T, typename ... U>
struct X<T(U......)> // this line is the important one
{ /* ... */ };

那么,这个代币是什么意思?

编辑: 看起来好像把“ ... ...”的标题改成了“ ... ...”,我的意思是“ ... ...”。 :)

8471 次浏览

这种怪异的每一个实例都与一个规则的单一省略号的实例相匹配。

  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 风格的 varargs 列表。

Here's a test supporting that theory… I think we have a new winner for worst pseudo-operator ever.

编辑: 这看起来是一致的。8.3.5/3描述了一种形成参数列表的方法

参数声明-listopt... opt

因此,双省略号由以参数包结尾的参数声明列表形成,后跟另一个省略号。

The comma is purely optional; §8.3.5/4 does say

如果句法正确,而且“ ...”不是抽象声明符的一部分,那么“ ...”就是“ ...”的同义词。

这个 在一个抽象声明程序 [edit]中,但 Johannes 指出了一个很好的观点,他们在一个参数声明中引用了一个抽象声明程序。我想知道为什么他们没有说“部分参数声明”,为什么这句话不仅仅是一个信息注释..。

此外,<cstdarg>中的 va_begin()在 varargs 列表之前需要一个参数,因此 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 );
}

在 vs2015上,分隔逗号在模板版本中是必不可少的:

    template <typename T, typename ... U>
struct X<T(U...,...)> {};// this line is the important one

一个示例实例是:

    X<int(int...)> my_va_func;

问候, FM.