【问题标题】:double parentheses around function parameter list函数参数列表周围的双括号
【发布时间】:2011-04-21 22:21:08
【问题描述】:

我有以下代码,它使用 gcc 4.4 编译,没有警告,并返回 42。

template<typename T>
struct foo
{ };

template<typename T>
struct foo<void (T)>
{
  enum { value = 42 };
};

int main()
{
  return foo<void ((int))>::value;
}

现在,我明白了为什么当模板参数为void (int) 时它应该起作用,但是双括号是怎么回事?这在 C++ 中合法吗?和void (int)一样吗?

干杯

【问题讨论】:

  • 我显然遗漏了一些东西......按喇叭,另一位用户认为有必要指出 C++ 不是 Python - 但为什么呢?这段代码在我看来完全不像 Python。
  • @delnan 在 Python 中额外的括号有特定的含义,但在 C++ 中则没有。笑话在需要解释的时候就不再好笑了。
  • @Mark:如果是基于错误信息的玩笑也不好笑。你们不知道任何Python吗?现在,(expr,) 将是一个单例元组,但 (expr) 只是 expr。在 Python 中,简单地将某些东西包装在括号中并不会改变它的任何内容,就像在每一种理智的语言中一样。
  • @Mark,@delnan,你是对的,下午晚些时候的brainfart。
  • 如果第二个 struct foo 是一个特化,那么模板行不应该是template &lt;&gt;吗?

标签: c++


【解决方案1】:

在这种情况下,void ((int))void (int) 相同。
void ((int)) 中的部分 foo&lt;void ((int))&gt; 称为 type-id
根据 §8.1/1,type-idtype-specifier-seqabstract-declarator.
void ((int)) 中,type-specifier-seqvoidabstract-declarator((int)), 和abstract-declarator可以任意括起来。
这在 C 和 C++ 中是合法的。

【讨论】:

  • 这就是答案。 void ((int)) 是一个有趣的 type-id,表示在有趣的声明 void (g(int)) 中声明了类型 g,这与更常见的声明 void g(int) 具有相同的含义。
【解决方案2】:

内括号用于更改表达式的计算顺序。当表达式只有一个部分时,顺序无关紧要,因此它们实际上什么都不做。

【讨论】:

  • 如果这是合法的,为什么g++会拒绝void f((int)) {}?我怀疑原始示例的语法无效,并且它被接受的事实是编译器错误。
  • 确实如此,但它适用于这里吗?表达式中的冗余括号无关紧要,但这是一种类型规范。
  • @Adrian,类型表达式也是表达式。在这种情况下,括号无关紧要,但有很多例子。
  • @aschepler,我认为你的例子是我上面提到的案例之一。通过告诉编译器在 int 处开始表达式求值,它看起来不再像函数规范。
  • 好的,但是这里仍然不涉及表达式或求值。
【解决方案3】:
  • 模板与宏不同。

  • 您的“void (T)”与“void T”相同,“void ((int))”与“void int”相同,就像“void (((((int))))”一样与“void int”相同。 括号中的表达式按照@Mark 指出的那样计算。

【讨论】:

  • 不涉及表达式,也不计算任何内容。
【解决方案4】:

在这种情况下,不需要用于此目的,但像这样使用双括号的主要原因是为了避免最麻烦的解析。

在函数声明中不允许使用双括号,但在函数调用中使用双括号,因此通过将至少一个参数括在双括号中,可以将原本会产生最麻烦的解析的代码强制为函数调用。

我在previous answer 中包含的一些代码证明了这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-24
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 2016-04-21
    • 1970-01-01
    相关资源
    最近更新 更多