可变参数模板中的声明符修饰符位置

Mar*_*cia 10 c++ variadic-templates c++11

声明符.是的,声明者.它们是许多编码约定辩论的来源.对于参数来说这是一个非常好的主题--C++并不排除哪一个比另一个好(它不关心!).所以我们可以写这些而不用担心有人会取笑你:

int x;

int& a = x;
int &b = x;

int* c = &x;
int *d = &x;
Run Code Online (Sandbox Code Playgroud)

在句法上,b并且d比其他人"更有效".我们需要在名称前加上声明符修饰符:

int m, *n;   // m is an int; n is a pointer to int
Run Code Online (Sandbox Code Playgroud)

但潮流似乎转而支持一个.使用C++ 11的可变参数模板,声明符的位置似乎仅限于修饰符更接近基本类型的形式:

template<typename... Ts>
void VariadicFuncRef(const Ts&... args) { }
                             ^
template<typename... Ts>
void VariadicFuncPtr(Ts*... args) { }
                       ^
Run Code Online (Sandbox Code Playgroud)

写这些表单是错误的:

template<typename... Ts>
void VariadicFuncRef(const Ts... &args) { }

template<typename... Ts>
void VariadicFuncPtr(Ts... *args) { }
Run Code Online (Sandbox Code Playgroud)

有关具体示例,请单击此处.

所以,我的问题是: 为什么我们仅限于这种(合法的)形式而不能使用另一种形式?

有什么想法吗?

附加1:我也对设计决定感兴趣,为什么这个"规则"被"强制执行".

Naw*_*waz 3

首先,我不会说int &aint& a. 你可能会说它更具可读性,或者是一个很好的实践,但这完全是另一回事。

其次,参数解包语法T...可以理解为“扩展左侧的类型模式...,形成与类型模式的形式匹配的相同或不同的实际函数参数类型”。所以写的时候f(T&...)可以扩展为f(int&, float&, double&, Xyz&, Abc&). 但当语法为 时,这似乎并不那么明显(至少对我来说)T...&。所以也许,这是标准这样做的其他几个可能的原因之一。

另请注意,argsinT&...args可选的。因此,如果你不写它,那么void f(T...&)看起来会很奇怪(至少对我来说),并且void f(T&...)至少在美学上看起来更好。

您还可以比较 :T * const & ...T... * const &. 前一种语法中的类型模式比后一种语法中的类型模式更明显。