【问题标题】:Why statements cannot appear at namespace scope?为什么语句不能出现在命名空间范围内?
【发布时间】:2011-12-12 04:49:30
【问题描述】:

关于标准中的哪个规则陈述如下陈述的任何想法:

p++; //where 'p' is pointer to array

不能出现在全局范围内?

如果可能的话,我正在寻找参考,而不仅仅是解释。

【问题讨论】:

  • 不就是可以有全局作用域的声明吗?
  • 您希望这样的语句何时运行?
  • 如果没有左操作数可用,我排除了要丢弃的值,但这给了我一个错误,但似乎没有提到它们不能出现在全局范围内。
  • p++ 不仅分配给一个左值(如果存在的话),它还增加了p 的值,所以这可以追溯到@JamesMcNellis 的评论。
  • @JimBuck:也没有积分表达式,

标签: c++ compiler-errors standards


【解决方案1】:

您编写的表达式p++ 位于命名空间范围内。 §7.3.1/1 中定义的 namespace-body 的语法是禁止的:

命名空间主体:
声明序列opt

这表示命名空间主体可以可选地包含 声明p++ 肯定不是声明,而是表达式,因此标准隐含地禁止它。标准可能有明确的声明禁止这样做,但我认为以上应该足够了。

同样,您不能这样做:

namespace sample
{
  f(10,10); //error
  std::cout << "hello world" << std::endl;//error
}

但是,如果您以某种方式将 表达式 转换为 声明(或者更确切地说 在声明中使用表达式),那么您可以评估所谓的表达式.这里有一个技巧:

#include<iostream>

namespace sample
{
  struct any { template<typename T> any(const T&){} };

  void f(int a,int b) { std::cout << a * b <<  std::endl; }

  any a1= (f(10,10), 0); //ok
  any a2 = std::cout << "hello world" << std::endl;//ok
}

int main() {}

输出(如果幸运的话):

100
hello world

在线演示:http://ideone.com/icbhh

注意f()的返回类型是void,这意味着我不能写下面的(see error)

any a1 = f(10,10); //error

这就是我使用 comma 运算符的原因,以便表达式可以具有一些值,该值的计算结果是逗号表达式中的最后一个操作数。对于std:cout,由于它返回std::ostream&amp;,我不需要使用逗号运算符;没有它也没关系。

上面代码中还有一个有趣的地方:为什么我在里面定义了any 和一个templated 构造函数?答案是,我写这个是为了给 any 类型的值赋值(不是双关语),无论是intstd::ostream&amp; 还是其他。 templated 构造函数可以接受任何类型的参数。

但是不要写这样的代码。它们不能保证按您期望的方式工作。

阅读本主题中的答案,您会明白为什么这种编码可能很危险:

【讨论】:

  • “它们不能保证按您期望的方式工作” - 除非您知道它们保证的工作方式。在这种情况下,它们的工作方式完全符合您的预期,但如果您有多个翻译单元,那就麻烦了。
  • @SteveJessop:另外,我之所以这么说是因为std::cout,因为在@987654339 时它可能还没有完全初始化(及其所有依赖项) @ 被调用。
  • 啊,好的。我不知道当std::cout 准备好使用时标准是怎么说的。在实践中,实现似乎会在必要时进行后空翻,以使其尽快可用。
  • 语法 namespace-body 没有被全局命名空间引用。对于全局命名空间,语法 translation-unit 改为适用。
【解决方案2】:

通过说“这样的陈述”,我猜你知道/为什么陈述一般不能在全局范围内。

p++;

是一个语句,因为它基本上被翻译成:

p = p + 1;

这是正常的说法。

【讨论】:

    【解决方案3】:

    当然是 Stroustrup 的“C++ 编程语言”。

    第 r.6.1 节讨论语句 - 可以是标签、表达式、复合语句、选择语句、迭代语句、跳转语句或声明语句。

    然后跳回到第 3.3.1 节,它显示了语句的语法和引用: 请注意......没有赋值语句或过程调用语句。赋值和函数调用作为表达式处理。

    r.3.1 节然后讨论了四种类型的作用域——本地、函数、文件和类。由于 global 本质上是“文件”范围。名称允许在全局范围内,就像首先在返回或参数类型中声明的类一样。

    真的找不到具体的明确规定,你不能在全局范围内有一个表达式语句,但是通过省略,引用显示了你可以拥有什么。

    【讨论】:

      猜你喜欢
      • 2020-04-06
      • 2022-07-06
      • 1970-01-01
      • 2019-05-11
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 2015-02-26
      相关资源
      最近更新 更多