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

时间:2011-04-11 18:15:08

标签: c++ c++11 variadic-templates

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

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

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

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

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

2 个答案:

答案 0 :(得分: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; };

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

Here's a test支持这个理论......我认为我们有一个新的胜利者,因为有史以来最糟糕的伪运营商。

修改:这似乎符合要求。 §8.3.5/ 3描述了将参数列表形成为

的一种方法
  

parameter-declaration-list opt ... opt

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

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

  

在语法正确且“......”不是抽象声明符的一部分的地方,“,...”与“...”同义。

这个在一个抽象声明器中, [edit] 但是约翰尼斯提出了一个很好的观点,即他们指的是参数声明中的抽象声明符。我想知道他们为什么不说“参数声明的一部分”,以及为什么这句话不只是一个内容丰富的说明......

此外,va_begin()中的<cstdarg>在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 );
}

答案 1 :(得分:2)

vs2015上的

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

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

示例实例化是:

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

的问候, FM。