116

在浏览 gcc 当前实现的新 C++11 标头时,我偶然发现了“......”标记。您可以检查以下代码是否可以正常编译[通过 godbolt.org]。

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

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

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

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

4

2 回答 2

80

这种奇怪的每个实例都与一个常规的单个省略号的情况配对。

  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 样式的可变参数列表。

这是一个支持该理论的测试......我认为我们有一个新的赢家,有史以来最差的伪操作员。

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

参数声明列表opt ... opt

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

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

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

在一个抽象声明符中,[编辑]但 Johannes 提出了一个很好的观点,即他们指的是参数声明中的一个抽象声明符。我想知道他们为什么不说“参数声明的一部分”,以及为什么这句话不仅仅是一个信息性注释……</p>

此外,va_begin()<cstdarg>可变参数列表之前需要一个参数,因此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 );
}
于 2011-04-11T18:32:25.780 回答
4

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

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

一个示例实例化是:

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

问候,调频。

于 2016-05-26T17:40:50.587 回答