范围解析运算符和常量

时间:2016-01-06 10:22:50

标签: c++

我们来看下面的代码:

#include <string> // std::string    
using namespace std;
int main() {
  //const::int i = 42;       -> Error: "expected id-expression before 'int'"
  const::string str = "Foo"; // No error: why?
}

为什么这段代码会编译?只有当XXX是基本类型时,才会出现错误“预期在XXX之前的id-expression”。

const::char c = 1;   // error: expected id-expression before 'char'
const::double d = 2; // error: expected id-expression before 'double'
const::float f = 3;  // error: expected id-expression before 'float'
const::bool b = 4;   // error: expected id-expression before 'bool'

4 个答案:

答案 0 :(得分:7)

const::string被解析为const ::string::string表示在全局命名空间中查找string,并且由于您已将std注入全局命名空间,因此找到std::string并且一切都很花哨。

int是一种内置类型,并且不在任何命名空间中,因此不存在::intstd::int这样的错误。

答案 1 :(得分:3)

::something告诉编译器在全局命名空间中查找something,但int是关键字(未在任何地方定义),而string(分别为std::string })是<string>中定义的类,所以你的代码等同于这个

#include <string> // std::string    
using namespace std;
int main() {
  //const ::int i = 42;       -> Error: "expected id-expression before 'int'"
  const ::string str = "Foo";
}

答案 2 :(得分:1)

它编译因为

using namespace std;

将整个std命名空间拉入全局命名空间,因此::stringstd::string相同。您的相关行实际上被解释为

const ::string str = "Foo";

但是,int是关键字(和基本类型),而不是驻留在任何命名空间中的用户定义的名称。所以::int没有意义。

答案 3 :(得分:0)

你的using namespace std;有点红鲱鱼。请注意,const::std::string str = "Foo";也会编译。这个编译的原因(以及你的const::string str = "Foo";编译的原因)是因为::是范围解析运算符。间距无关紧要。正如a+b+ca + b + c之间没有区别一样,const::string strconst :: string str之间没有区别(同样,const::std::string strconst :: std :: string str之间也没有区别

::::std::std::都是嵌套名称说明符的示例,在c ++的5.1.1¶8中有描述n3290(C ++ 11标准的草案)。 const是一个关键字,不能将其解释为嵌套名称说明符的主要部分。这意味着const::string只能被解释为您已编写const ::string

在全局命名空间级别using namespace std;的上下文中,使用::string没有任何问题,因为前导::意味着查找全局命名空间中的后续内容。您已将所有命名空间std拉入全局命名空间。因此,const::string strstr声明为const - std::string类型的合格变量。

const::int i = 42;怎么样?这种结构的标准中没有地方。看7.1.6.2¶1(c ++ n3290),简单类型说明符

  • type-name ,可选择以嵌套名称说明符开头,
  • 嵌套名称说明符 模板 simple-template-id
  • 其中一个内置基元类型
  • 自动关键字或
  • decltype-specifier

类型名称类名枚举名 typedef-name ,或 simple-template-id 。内置基元类型不属于类型名称的类别。这意味着以下将(并且确实)编译:

#include <string> 
#include <iostream>

typedef int Int; // Now we can use ::Int because Int is a type-name.

using namespace std;
int main() {
  const::Int i = 42;         // No error.
  const::string str = "Foo"; // No error.
  cout << i << ' ' << str << '\n';
}