【问题标题】:Declarator modifier position in variadic templates可变参数模板中的声明符修饰符位置
【发布时间】:2012-12-06 12:35:31
【问题描述】:

声明符。是的,声明者。它们是许多编码约定辩论的根源。对于争论来说,这是一个非常好的话题——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:我也对为何“强制执行”此“规则”的设计决策感兴趣。

【问题讨论】:

  • @Nawaz 当我花了几分钟试图用错误的语法编译代码时,我想到了。经验教训:永远不要使用您不熟悉的功能。
  • 这将恢复你的世界:三个 ... 也是声明符的一部分!
  • 您也可以说“我的变量名的第一个字符的位置被限制在更接近基本类型的位置”。恕我直言,这是一件很奇怪的事情。
  • 可能是因为声明符部分也可以使用包(函数或数组声明符)

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


【解决方案1】:

旧的声明符语法只是一个带有微不足道的空白的规则,但您的想法是两个。我怀疑委员会是否会赞成制定两条规则,如果一条就足够了。

选择将声明符放在左边很可能有两个原因:

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

【讨论】:

  • @MarkGarcia std::forward&lt;Ts&gt;(args)..., args 将包扩展到... 的左侧,而不是右侧。
  • 好的。这完全出乎我的意料 (std::forward)。但我在学习! (无需赘述std::forward
【解决方案2】:

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

第二,参数解包语法T...可以读作...左侧的type-pattern被展开,形成与type-形式匹配的相同或不同的实际函数参数类型-模式”。所以当你写f(T&amp;...)时,它可以扩展为f(int&amp;, float&amp;, double&amp;, Xyz&amp;, Abc&amp;)。但是当语法为T...&amp; 时,这似乎并不那么明显(至少对我而言)。所以也许,这就是标准做出这样的几个其他可能的原因之一。

还要注意T&amp;...args 中的args可选。所以如果你不写,那么void f(T...&amp;) 看起来很奇怪(至少在我看来),而void f(T&amp;...) 至少在美学上看起来更好。

您还可以比较以下语法:T * const &amp; ...T... * const &amp;type-pattern 在前一种语法中比在后一种语法中更明显。

【讨论】:

  • 好点。唉,我们也可以说T... &amp;arg 中的&amp;args(如果这是有效的)扩展为int&amp;, float&amp;...
  • 您的回答让我有些信服。非常感谢。但我也可以使用第三方的意见。我希望你能等得起。
【解决方案3】:

达到完美,不是没有什么可添加的,而是没有什么可带走的。

-- 安托万·德·圣埃克苏佩里

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

  • 它们必须在编译器中专门编码
  • 它们存在引入错误的风险
  • 它们存在与其他功能/变体发生不良交互的风险
  • ...

C 和 C++ 中的语法(大部分)对空格不敏感,因此无论您将 &amp;* 放在何处,这两种偏好都可以共存而无需额外负担;然而,在可变参数模板的情况下,由于... 令牌,它确实很重要。委员会因此决定选择一个,他们选择了 C++ 中最惯用的一个(强调完整类型而不是基本类型)。

【讨论】:

    猜你喜欢
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多