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

时间:2012-12-19 07:41:00

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

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

int x;

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

int* c = &x;
int *d = &x;

在句法术语中,bd比其他人“更有效”。我们需要在名称之前加上声明符修饰符:

int m, *n;   // m is an int; n is a pointer to int

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

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

写这些表格是错误的:

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

template<typename... Ts>
void VariadicFuncPtr(Ts... *args) { }

有关具体示例,请点击here

所以,我的问题是: 为什么我们仅限于此(合法)表单而不能使用另一个?

有什么想法吗?

附加1:我也对设计决定感兴趣,为什么这条“规则”被“强制执行”。

3 个答案:

答案 0 :(得分:4)

旧的声明符语法只是一个带有微不足道的空格的规则,但你的想法是两个。我怀疑委员会会赞成在一个足够的情况下制定两条规则。

将声明者放在左侧的选择很可能有两个原因:

  • 惯用C ++现在更喜欢int* x而不是int *x(例如Bjarne使用前者)。大多数人认为声明者语法是错误的。
  • 参数包扩展会将内容扩展到...左侧,而不是右侧。

答案 1 :(得分:3)

首先,我不会说int &a int& a更有效。你可能会说它更具可读性或者是一种好的做法,但这完全是另一回事。

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

另请注意,args中的T&...args 可选。所以,如果你不写它,那么void f(T...&)看起来很奇怪(至少对我来说),而void f(T&...)至少看起来更美观。

您还可以将T * const & ...T... * const &等语法进行比较。 type-pattern 在前一种语法中比在后一种语法中更明显。

答案 2 :(得分:2)

  

实现完美,而不是在没有其他任何东西可以添加的情况下,但是当没有任何东西可以带走时。

     

- Antoine de Saint-Exupery

编程语言设计的难点不是添加功能,而是不添加功能。每个功能,每种语法变体都有成本:

  • 必须在编译器中专门编码
  • 他们冒着引入错误的风险
  • 他们冒着与另一个功能/变体进行严重互动的风险
  • ...

C和C ++中的语法(大多数)是空格不敏感的,因此放置&*的位置并不重要,两个首选项可以共存而不会有额外的负担;但是对于可变参数模板,由于...令牌,它确实很重要。因此,委员会选择了一个,他们选择了C ++中最惯用的(强调完整类型而不是基类型)。