简体   繁体   English

范围解析运算符和const

[英]Scope resolution operator and const

Let's take the following code: 让我们看下面的代码:

#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?
}

Why does this code compiles? 为什么要编译此代码? The error "expected id-expression before XXX" is only present when XXX is a fundamental type. 仅当XXX是基本类型时,才会出现错误“ XXX之前的预期id表达式”。

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'

const::string is parsed as const ::string . const::string被解析为const ::string ::string means to look up string in the global namespace, and since you have injected std into the global namespace, std::string is found and everything is dandy. ::string表示在全局名称空间中查找string ,并且由于您已将std注入全局名称空间,因此找到了std::string ,并且所有操作都变得很花哨。

int is a built-in type and isn't in any namespace, so there's no such thing as ::int or std::int , hence the error. int是内置类型,不在任何名称空间中,因此不存在::intstd::int的错误。

::something tells the compiler to look for something in global namespace, but int is keyword (not defined anywhere), while string (resp. std::string ) is class defined in <string> so your code is equivalent to this one ::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";
}

It compiles because 它之所以编译是因为

using namespace std;

pulls the entire std namespace into the global namespace, so ::string is the same as std::string . 将整个std名称空间放入全局名称空间,因此::stringstd::string相同。 Your line in question is actually interpreted as 您所讨论的行实际上被解释为

const ::string str = "Foo";

However, int is a keyword (and a fundamental type), and not a user-defined name that resides in any namespace. 但是, int是关键字(和基本类型),而不是驻留在任何名称空间中的用户定义名称。 So ::int doesn't make sense. 所以::int没有意义。

Your using namespace std; 您正在using namespace std; is bit of a red herring. 有点红鲱鱼。 Note that const::std::string str = "Foo"; 注意const::std::string str = "Foo"; also compiles. 也可以编译。 The reason this compiles (and the reason your const::string str = "Foo"; compiles) is because :: is the scope resolution operator. 之所以进行编译(以及您的const::string str = "Foo";编译的原因)是因为::是作用域解析运算符。 Spacing is irrelevant. 间距无关紧要。 Just as there's no difference between a+b+c and a + b + c , there's no difference between const::string str and const :: string str (and similarly, between const::std::string str and const :: std :: string str ). 就像a+b+ca + b + c之间没有区别一样, const::string strconst :: string str之间也没有区别(同样, const::std::string strconst :: std :: string str之间也没有区别) const :: std :: string str )。

:: , ::std:: , and std:: are all examples of a nested-name-specifier , which is described in 5.1.1 ¶8 of c++ n3290 (a draft of the C++11 standard). ::::std::std::都是嵌套名称说明符的所有示例,在c ++ n3290(C ++ 11标准的草案)的5.1.1¶8中进行了描述。 The const is a keyword and this cannot be interpreted as the leading part of a nested-name-specifier . const是一个关键字,不能将其解释为nested-name-specifier的开头 This means that const::string can only be interpreted as if you had written const ::string . 这意味着const::string只能像您已经写过const ::string一样被解释。

In the context of using namespace std; using namespace std;的上下文中using namespace std; at global namespace level, there's nothing wrong with using ::string because the leading :: means to look up what follows in the global namespace. 在全局名称空间级别,使用::string没什么问题,因为前导::表示查找全局名称空间中的内容。 You've pulled all of namespace std into the global namespace. 您已将所有名称空间std放入全局名称空间。 Thus const::string str declares str as a const -qualified variable of type std::string . 因此const::string str声明了str作为const -qualified类型的可变std::string

What about const::int i = 42; 那么const::int i = 42; ? There's no place in the standard for such a construct. 在这种构造的标准中没有地方。 Looking at 7.1.6.2 ¶1 (c++n3290), A simple-type-specifier is 看7.1.6.2¶1(c ++ n3290),一个简单类型说明符

  • A type-name , optionally preceded by a nested-name-specifier , 类型名称 ,可以选择在其后加一个嵌套名称说明符
  • A nested-name-specifier template simple-template-id , 嵌套名称说明符 模板 simple-template-id
  • One of the built-in primitive types, 内置原始类型之一,
  • The auto keyword, or auto关键字,或
  • A decltype-specifier . 十进制类型说明符

A type-name is a class-name , an enum-name , a typedef-name , or a simple-template-id . 类型名称类名称枚举名称typedef名称simple-template-id The built-in primitive types do not fall in the category of a type-name . 内置基本类型不属于type-name的类别。 This means that the following will (and does) compile: 这意味着以下将(并确实)进行编译:

#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';
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM