"......"令牌是什么意思?即参数包上的双省略运算符

Vit*_*tus 110 c++ variadic-templates c++11

在浏览gcc当前新C++ 11标头的实现时,我偶然发现了"......"令牌.您可以检查,以下代码编译正常 [通过ideone.com].

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

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

那么,这个令牌的含义是什么?

编辑:看起来如此修剪"......"的问题标题为"......",我的意思是"......".:)

Pot*_*ter 78

每个奇怪的实例都与常规单个省略号的情况配对.

  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; };
Run Code Online (Sandbox Code Playgroud)

我的猜测是双省略号的含义相似,即可_ArgTypes..., ...变参数模板扩展后跟一个C风格的varargs列表.

这是一个支持该理论的测试 ...我认为我们有一个新的胜利者,因为有史以来最糟糕的伪操作者.

编辑:这似乎符合要求.§8.3.5/ 3描述了将参数列表形成为的一种方法

parameter-declaration-list opt ... opt

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

逗号纯粹是可选的; §8.3.5/ 4确实说

在语法正确且"......"不是抽象声明者的一部分的地方,",......"与"......"同义.

在一个抽象声明器中,[编辑]但约翰尼斯提出了一个很好的观点,即他们指的是参数声明中的抽象声明符.我想知道他们为什么不说"参数声明的一部分",以及为什么这句话不只是一个信息性的说明......

此外,va_begin()<cstdarg>varargs列表之前需要一个参数,因此f(...)C++特别允许的原型是无用的.与C99交叉引用,在普通C中是非法的.所以,这是最奇怪的.

使用说明

根据要求,这里是双省略号的演示:

#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 );
}
Run Code Online (Sandbox Code Playgroud)

  • @Bo Persson:`std :: is_function`的`value`必须为true,即使函数是C varargs one,因为T(U ...)****不匹配这样的函数,你需要这个疯狂.例如int f(int,char,...)与T = int,U = {int,char}和"..."varargs标记完全匹配T(U ......). (12认同)
  • "这*在一个抽象声明器中是*" - >它们不代表同一参数类型列表的最后一个参数的抽象声明符的一部分.例如`void(int ...)`这里,```不是abstract-declarator`int`的一部分,因此它与`void(int,...)`同义.如果你写`void(T ...)`和`T`是模板参数包,```将是abstract-declarator的一部分,因此它不等于`void(T, ...)`. (4认同)
  • "此外,<cstdarg>中的va_begin()在varargs列表之前需要一个参数,因此C++特别允许的原型f(...)是无用的." - 如果你想知道传递了什么参数,那将是无用的.`f(...)`在模板元编程中被大量用作回退函数重载,其中这些信息不是必需的(并且函数甚至实际上都没有被调用). (2认同)