C++ “a”究竟是什么;“尾部参数包”;

C++ “a”究竟是什么;“尾部参数包”;,c++,c++11,language-lawyer,variadic-templates,overloading,C++,C++11,Language Lawyer,Variadic Templates,Overloading,在解决函数模板重载之间的歧义时,会执行偏序(有关一些解释,请参阅)。在该网站上,我们还了解到 在平局的情况下,如果一个函数模板有一个尾随参数 pack,而另一个没有,省略参数的是 被认为比空的更专业 参数包 现在,我想知道后面的参数包到底是什么。如果有 template<class ...> struct tuple { /* ... */ }; template<class T, class...Ts> void foo(tuple<T,Ts...>);

在解决函数模板重载之间的歧义时,会执行偏序(有关一些解释,请参阅)。在该网站上,我们还了解到

在平局的情况下,如果一个函数模板有一个尾随参数 pack,而另一个没有,省略参数的是 被认为比空的更专业 参数包

现在,我想知道后面的参数包到底是什么。如果有

template<class ...> struct tuple { /* ... */ };

template<class T, class...Ts> void foo(tuple<T,Ts...>);

template<class T, class...Ts> void bar(T, Ts...);
模板结构元组{/*…*/};
模板void-foo(元组);
模板空心条(T、Ts…);
是,哪个不是,为什么?还请注意,clang考虑

template<class T> void f(tuple<T>);

template<class T, class...Ts> void f(tuple<T,Ts...>);

int main()
{  f(tuple<int>());  }   // ambiguous call?
模板void f(元组);
模板void f(元组);
int main()
{f(tuple());}//不明确的调用?
模棱两可,这意味着
foo
没有后续参数包。

这是一个缺陷,最近在C++17标准草案中投票表决。以下内容已添加到[临时扣除部分]:

…[如果]函数模板
F
至少与函数模板
G
一样专业,反之亦然,如果
G
有一个尾随参数包,而
F
没有相应的参数,如果
F
没有尾随参数包,那么
F
G
更专业

该标准没有明确定义“尾部参数包”的含义,但根据使用该术语的现有上下文判断,它指的是在模板参数列表中显示为最右侧参数的模板参数包:

template<class T, class... U> struct X;
//                ^^^^^^^^^^
template<class T, class... U> void y(T, U...);
//                                      ^^^^
GCC将此视为第二个重载
g
的有效调用;叮当声把它当作模棱两可。Clang的正确性可能取决于“后续参数包”是包含后续模板参数包,还是仅包含后续功能参数包

请注意,两个编译器都同意
C
在以下示例中引用类模板
C
的第二个部分专门化:

template<class...> struct C;

template<class T, class... U> struct C<T, U...> {};
template<class T> struct C<T> {};
模板结构C;
模板结构C{};
模板结构C{};
这在Clang中似乎是不一致的,因为类模板专门化的偏序的标准规则是根据函数模板的偏序定义的。参见。

表示“在……的末尾”

尾部参数包是在模板参数列表末尾找到的参数包:

template <typename T1, typename... Ts>
void foo();

// ^ Ts... is trailing here
模板
void foo();
//^Ts。。。这是尾随的

<>这不是一个C++问题,而是一个英语问题。

LOL,这两个评论相互矛盾!所以这里确实有一些需要讨论的地方。@Jarod42所以你说“trailing parameter pack”指的是函数参数,而不是模板参数?确实,clang和gcc不同意。CWG1395的决议刚刚被表决为最新的工作草案,请参阅。我想这就是参考文本的来源。不幸的是,它似乎没有解决1432,这不是我在那里看到的唯一问题。要获得更多乐趣,请查看。只是做了一个快速测试,MSVC同意GCC:。老实说,我有点惊讶,他们比Clang更快地解决了
g()
版本。有没有不拖尾的参数包?@m.m
template void h(tuple)
@Walter我自己的权威不足以说服我自己,所以我一直在尝试提供一些逻辑论点。我认为,我们最好的权威回应是让CWG的人出现在这里或在这里,告诉我们他们起草新措辞时的意图。不管那是什么,我认为在措辞上还有更多的工作要做,正如在聊天中所讨论的。是的。。。也许在一个更简单的宇宙里,一个充满。。。轻,一个包是透明的实体愉快。。。互相比赛,试图找出谁是落后的。当然,如果他们都。。。在围绕标准黑洞的轨道上,那么就没有一个是真正的尾随。现在我更糊涂了。@Walter:
模板
@LightnessRacesinOrbit那是
。。。Ts
,但不是
Ts.
,虽然有细微的不同,但仍然不同。顺便说一句,这正是问题的症结所在:它是尾随的
…Ts
还是尾随的
Ts…
?博格丹认为,它只能指后者,但即使在标准中似乎也没有明确的含义。@Walter:那是不同的。声明上写着
typename。。。Ts
但要将其解包,您需要编写
Ts.
。所有这些都与问题或答案无关。那么,为什么代码注释中有一个包扩展呢?
template<class...> struct C;

template<class T, class... U> struct C<T, U...> {};
template<class T> struct C<T> {};
template <typename T1, typename... Ts>
void foo();

// ^ Ts... is trailing here