Qualified name lookup

Unqualified identifiers(omitted)

Besides suitably declared identifiers, the following can be used in expressions in the same role:

  • an overloaded operator name in function notation, such as operator+ or operator new
  • a user-defined conversion function name, such as operator bool
  • a user-defined literal operator name, such as operator "" _km
  • a template name followed by its argument list, such as MyTemplate<int>
  • the character ~ followed by a class name, such as ~MyClass
  • the character ~ followed by a decltype specifier, such as ~decltype(str)

Together with identifiers they are known as unqualified id-expressions.

Qualified identifiers

A qualified id-expression is an unqualified id-expression prepended by a scope resolution operator ::, and optionally, a sequence of enumeration, (since C++11)class or namespace names or decltype expressions (since C++11) separated by scope resolution operators.

std::string::npos
::tolower
std::cout
boost::signals2::connection

###Qualified name lookup
A qualified name is a name that appears on the right hand side of the scope resolution `operator ::` (see also qualified identifiers). A qualified name may refer to a
* [enumeration](#enumerations)
* [**class member**](#class)(including static and non-static function,types,templates.etc)
* [**namespace member**](#namespace)(including another namespace)

If there is nothing on the left hand side of the ::, the lookup considers only declarations made in the global namespace scope(or introduced into the global namespace by a using declaration).

Example hided std namespace

#include <iostream>
int main()
{
struct std {};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std,global namespace }

Before name lookup can be performed for the name on the right hand side of ::, lookup must be completed for the name on its left hand side (unless a decltype expression is used, or there is nothing on the left). This lookup, which may be qualified or unqualified, depending on whether there's another :: to the left of that name, considers only namespaces, class types, enumerations, and templates whose specializations are types:

在name lookup执行之前,要检查name的完整性,::右边的name在左边的scope中,则是qualified,否则为unqualified。

::右边的名字必须在::左边的namespace or class types or enumeration or templates whose specializations are types 中。

struct A {
static int n;
};
int main() {
int A;
A::n = 42; // OK: unqualified lookup of A to the left of :: ignores the variable
A b; // error: unqualified lookup of A finds the variable A
}

When a qualified name is used as a declarator, then lookup of all names used in the same declarator that follow that qualified name, but not the names that precede it, is performed as if qualified the same way:

class X { };
constexpr int number = 100;
class C {
class X { };
static const int number = 50;
static X arr[number];
};
X C::arr[number], brr[number]; // Error
// Every name in the declarator "C::arr[number]" after "C::arr"
// is looked up within C::, but the names before C::arr are unaffected,
// The names in the second declarator ("brr[number]") are also unaffected
// equivalent to:
// "::X C::arr[C::number], brr[::number]"
// 这与声明 int *a,b;一样,a是一个int*类型,而b是一个int类型
// 因为在X类型中找不到
C::X C::arr[number], brr[number]; // Compiles, size of arr is 50, size of brr is 100

destructor的lookup

If the name on the right hand side of :: is a destructor or pseudo-destructor (that is, the character ~ followed by an identifier), that identifier is looked up in the same scope as the name on the left hand side of ::.

struct C { typedef int I; };
typedef int I1, I2;
extern int *p, *q;
struct A { ~A(); };
typedef A AB;
int main() {
p->C::I::~I(); // the name I after ~ is looked up in the same scope as I before ::
// (that is, within the scope of C, so it finds C::I)
q->I1::~I2(); // The name I2 is looked up in the same scope as I1
// that is, from the current scope, so it finds ::I2
AB x;
x.AB::~AB(); // The name AB after ~ is looked up in the same scope as AB before ::
// that is, from the current scope, so it finds ::AB
}

###Enumerations
Enumerators
If the lookup of the left-hand side name comes up with an enumeration (either scoped or unscoped), the lookup of the right-hand side must result in an enumerator that belongs that enumeration, otherwise the program is ill-formed.

###Class members
If the lookup of the **left hand side name** comes up with a class/struct or union name, the name on the right hand side of `::` is looked up in the scope of that class (and so may find a declaration of a member of that class or of its base), with the following exceptions
* destructor name is looked up as described above (in the scope of the name to the left of `::`)
* user-defined conversion function name is TODO
* names used in **template argument** are looked up in the current scope(not int the scope of template name)
* names in using-declarations also consider class/enum names that are hidden in current scope

编译器中constructor的产生

If the right hand side of :: names the same class as the left hand side, the name designates the constructor of that class.

Such qualified name can only be used in a declaration of a constructor and in the using-declaration for an inheriting constructor.

In those lookups where function names are ignored (that is, when looking up a name on the left of ::, when looking up a name in elaborated type specifier, or base specifier), the same syntax resolves to the injected-class-name:

struct A { A(); };
struct B : A { B(); };
A::A() { } // A::A names a constructor, used in a declaration
B::B() { } // B::B names a constructor, used in a declaration
B::A ba; // B::A names the type A (looked up in the scope of B)
A::A a; // Error, A::A does not name a type struct A::A a2; // OK: lookup in elaborated type specifier ignores functions
// so A::A simply names the class A as seen from within the scope of A
// (that is, the injected-class-name)

Qualified name lookup can be used to access a class member that is hidden by a nested declaration or by a derived class. A call to a qualified member function is never virtual

struct B { virtual void foo(); };
struct D : B { void foo() override; };
int main()
{
D x;
B& b = x;
b.foo(); // calls D::foo (virtual dispatch)
b.B::foo(); // calls B::foo (static dispatch)
}

###Namespace members
1. If the name on the left of :: refers to a namespace or if there is nothing on the left of :: (in which case it refers to the global namespace), the name that appears on the right hand side of :: is looked up in the scope of that namespace, except that
* names used in **template arguments** are looked up int the current scope.
```cpp
namespace N {
template struct foo {};
struct X {};
}
N::foo x; // error: X is looked up as ::X, not as N::X
```

在namespace N内的qualified lookup首先会考虑到位于N内的和N内的inline namespace 成员(具有传递性)。

2. Qualified lookup within the scope of a namespace N first considers all declarations that are located in N and all declarations that are located in the inline namespace members of N (and, transitively, in their inline namespace members).

之后才会考虑到使用use-derectives引入的namespace和inline namespace(使用use-derectives引入的namespace)

3. If there are no declarations in that set then it considers declarations in all namespaces named by using-directives found in N and in all transitive inline namespace members of N. The rules are applied recursively:

int x;
namespace Y {
void f(float);
void h(int);
}
namespace Z {
void h(double);
}
namespace A {
using namespace Y;
void f(int);
void g(int);
int i;
}
namespace B {
using namespace Z;
void f(char);
int i;
}
namespace AB {
using namespace A;
using namespace B;
void g();
}
void h()
{
AB::g(); // AB is searched, AB::g found by lookup and is chosen AB::g(void)
// (A and B are not searched)
AB::f(1); // First, AB is searched, there is no f
// Then, A, B are searched
// A::f, B::f found by lookup
// (but Y is not searched so Y::f is not considered)
// overload resolution picks A::f(int)
AB::x++; // ERROR First, AB is searched, there is no x
// Then A, B are searched. There is no x
// Then Y and Z are searched. There is still no x: this is an error
AB::i++; // ERROR AB is searched, there is no i
// Then A, B are searched. A::i and B::i found by lookup: this is an error
AB::h(16.8); // First, AB is searched: there is no h
// Then A, B are searched. There is no h
// Then Y and Z are searched.
// lookup finds Y::h and Z::h. Overload resolution picks Z::h(double)
}
  1. It is allowed for the same declaration to be found more than once:
namespace A { int a; }
namespace B { using namespace A; }
namespace D { using A::a; }
namespace BD {
using namespace B;
using namespace D;
}
void g()
{
BD::a++; // OK: finds the same A::a through B and through D
}

Qualified name lookup的更多相关文章

  1. Name lookup

    Name lookup Types of lookup Argument-dependent lookup Template argument deduction overload resolutio ...

  2. 你或许不了解的C++函数调用(1)

    这篇博客名字起得可能太自大了,搞得自己像C++大牛一样,其实并非如此.C++有很多隐藏在语法之下的特性,使得用户可以在不是特别了解的情况下简单使用,这是非常好的一件事情.但是有时我们可能会突然间发现一 ...

  3. Identifiers

    Identifier An identifier is an arbitrarily long sequence of digits, underscores, lowercase and upper ...

  4. C++函数调用

    C++函数调用(1) 这篇博客名字起得可能太自大了,搞得自己像C++大牛一样,其实并非如此.C++有很多隐藏在语法之下的特性,使得用户可以在不是特别了解的情况下简单使用,这是非常好的一件事情.但是有时 ...

  5. Unqualified name lookup

    Unqualified name lookup File scope Namespace scope For an qualified name, that is a name that does n ...

  6. SQL Server-聚焦移除Bookmark Lookup、RID Lookup、Key Lookup提高SQL查询性能(六)

    前言 前面几节都是讲的基础内容,本节我们讲讲索引性能优化,当对大数据进行处理时首先想到的就是索引,一旦遇到这样的问题则手忙脚乱,各种查资料,为何平常不扎实基本功呢,我们由浅入深,简短的内容,深入的理解 ...

  7. Salesforce的sharing Rule 不支持Lookup型字段解决方案

    Salesforce 中 sharing rule 并不支持Look up 字段 和 formula 字段.但在实际项目中,有时会需要在sharing rule中直接取Look up型字段的值,解决方 ...

  8. eclipse调试(debug)的时候,出现Source not found,Edit Source Lookup Path,一闪而过

    问题描述 使用Eclipse调试代码的时候,打了断点,经常出现Source not found,网上找了半天,大部分提示点击Edit Source Lookup Path,添加被调试的工程,然而往往没 ...

  9. mongodb 3.x 之实用新功能窥看[2] ——使用$lookup做多表关联处理

    这篇我们来看mongodb另一个非常有意思的东西,那就是$lookup,我们知道mongodb是一个文档型的数据库,而且它也是最像关系型数据库的 一种nosql,但是呢,既然mongodb是无模式的, ...

随机推荐

  1. IOS 特定于设备的开发:处理基本方向

    UIDevice类使用内置的orientation属性获取设备的物理方向.IOS设备支持这个属性的7个可能的值. >UIDeviceOrientationUnknown:方向目前未知. > ...

  2. .NET DataGrid 导出Excel 无分页

    #region 导出Excel // protected void BtnExcelClick(object sender, EventArgs e) { ToExcel(); } public vo ...

  3. 解决[warn] _default_ VirtualHost overlap on port 80, the first has precedence问题

    问题背景: 在apache的httpd.conf里新增加了1个VirtualHost,域名是xxx.com,此时,服务器总共2个VirtualHost ,service httpd restart的时 ...

  4. Thread和ExecutorService(一)

    ExecutorService是Java并发包里面的一个线程池服务   线程池的优点 复用已有的线程,消除任务中创建线程的开销 通过优化线程的数量,提高性能,保证处理器一直处于忙的状态,而不必创建这么 ...

  5. python学习(序章)

    好久没写过笔记了,最近听说写博客笔记能使知识记忆更深刻,于是就开始写写,不为推广,只为增加记忆.好了,开始python的学习: 学习一门语言的快慢,与人无关,主要是与学习的目的有关,python语言目 ...

  6. ASP.NET之电子商务系统开发-3(订单)

    一.前言 继上次的购物车,这是第三篇.记录一下订单功能.这功能做的时候,走过弯路,很是烧脑,因为思路没理顺,数据库设计的也不怎么好,做到一半才发现有问题,接着把数据库重新设计好,理清思路后,终于完成了 ...

  7. JavaScript基础(简介、语法)

    一.JavaScript简介 1.JavaScript是个什么东西? 它是个脚本语言,需要有宿主文件,它的宿主文件是HTML文件. 2.它与Java什么关系? 没有什么直接的联系,Java是Sun公司 ...

  8. window.parent与window.opener的区别与使用

    window.parent 是iframe页面调用父页面对象 举例: a.html 如果我们需要在b.html中要对a.html中的username文本框赋值(就如很多上传功能,上传功能页在ifrma ...

  9. linux定时任务crontab的设置

    linux定时任务crontab的设置http://www.blogjava.net/freeman1984/archive/2010/09/23/332715.html vi /etc/cronta ...

  10. [Swust OJ 360]--加分二叉树(区间dp)

    题目链接:http://acm.swust.edu.cn/problem/360/ Time limit(ms): 1000 Memory limit(kb): 65535   Description ...