Unqualified name lookup

For an qualified name, that is a name that does not appear to the right of a scope resolution operator::, name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

Note: lookup from some context skips some declaration, for example, lookup of the name used to the left of ::ignores function, variable, and enumeration declarations, lookup of a name used as a base class specifier ignores all non-types declaration.

For the purpose of unqualified name lookup, all declarations from a namespace nominated by a using directive appear as if declared in the nearest enclosing namespace which contains, directly or indirectly, both the using-directly and the nominated namespace.

File scope(global namespace)

For a name used in global (top-level namespace) scope, outside of any function, class, or user-declared namespace, the global scope before the use of the name is examined:

int n = 1;     // declaration of n
int x = n + 1; // OK: lookup finds ::n int z = y - 1; // Error: lookup fails
int y = 2; // declaration of y int main() {}

###Namespace scope
For a name used in a user-declared namespace outside of any function or class, this namespace is searched before the use of the name, then the namespace enclosing this namespace before the declaration of this namespace, etc until the global namespace is reached.

int n = 1; // declaration
namespace N {
int m = 2;
namespace Y {
int x = n; // OK, lookup finds ::n
int y = m; // OK, lookup finds ::N::m
int z = k; // Error: lookup fails
}
int k = 3;
}

Non-member function definition

For a name used in the definition of a function, either in its body or as part of default argument, where the function is a member of user-declared or global namespace, the block in which the name is used is searched before the use of the name, then the enclosing block is searched before the start of that block, etc, until reaching the block that is the function body.

Then the namespace in which the function is declared is searched until the definition (not necessarily the declaration) of the function that uses the name, then the enclosing namespaces, etc.

namespace A {
namespace N {
void f();
int i=3; // found 3rd (if 2nd is not present)
}
int i=4; // found 4th (if 3rd is not present)
} int i=5; // found 5th (if 4th is not present) void A::N::f() {
int i = 2; // found 2nd (if 1st is not present)
while(true) {
int i = 1; // found 1st: lookup is done
std::cout << i;
}
} // int i; // not found namespace A {
namespace N {
// int i; // not found
}
}

Class definition

For a name used anywhere in class definition, except inside a member function body, a default argument of a member function, exception specification of a member function, in-class brace-or-equal initializer of a data member, or inside a nested class definition (including names of the bases from which the nested class is derived), the following scopes are searched:

  • a) the body of the class in which the name is used until the point of use and the entire body of its base class(es)
  • b) if this class is nested, the body of the enclosing class until the declaration of this class and the entire body of the base class(es) of the enclosing class.
  • c) if this class is local, or nested within a local class, the block scope in which the class is defined until the point of definition
  • d) if this class is a member of a namespace, or is nested in a class that is a member of a namespace, or is a local class in a function that is a member of a namespace, the scope of the namespace is searched until the definition of the class, enclosing class, or function. if the lookup of for a name introduced by a friend declaration: in this case only the innermost enclosing namespace is considered, otherwise lookup continues to enclosing namespaces until the global scope as usual.
namespace M {
// const int i = 1; // never found
class B {
// const const int i = 3; // found 3nd (but later rejected by access check)
};
}
// const int i = 5; // found 5th
namespace N {
// const int i = 4; // found 4th
class Y : public M::B {
// static const int i = 2; // found 2nd
class X {
static const int i = 1; // found 1st
int a[i]; // use of i
// static const int i = 1; // never found
};
// static const int i = 2; // never found
};
// const int i = 4; // never found
}
// const int i = 5; // never found

Injected class name

For the name of a class or class template used within the definition of that same class or template, unqualified name lookup finds the class that's being defined as if the name was introduced by a member declaration (with public member access)

Member function definition

For a name used inside a member function body, a default argument of a member function, exception specification of a member function, in-class brace-or-equal initialization of a data member, or inside a nested class definition (including names of the bases from which the nested class is derived), the scopes searched are the same as in class definition, except that the entire scope of the class is considered, not just the part prior to the declaration that uses the name.

For nested classes the entire body of the enclosing class is searched.

class B {
// int i; // found 3rd
};
namespace M {
// int i; // found 5th
namespace N {
// int i; // found 4th
class X : public B {
// int i; // found 2nd
void f();
// int i; // found 2nd as well
};
// int i; // found 4th
}
}
// int i; // found 6th
void M::N::X::f()
{
// int i; // found 1st
i = 16;
// int i; // never found
}
namespace M {
namespace N {
// int i; // never found
}
}

Dominance in virtual inheritance

Either way, when examining the bases from which the class is derived, the following rules, sometime referred to as dominance in virtual inheritance are followed:

  • A member name found in a sub-object B hides the same member name in any sub-object A if A is a base class sub-object of B.

Note that this does not hide the name in any additional, non-virtual, copies of A on the inheritance lattice that aren't bases of B: this rule only has an effect on virtual inheritance.

  • Names introduced by using-declarations are treated as names in the class containing the declaration.

a) After examining each base, the resulting set must either include declarations of a static member from subobjects of the same type, or declarations of non-static members from the same subobject.

b) A lookup set is constructed, which consists of the declarations and the subobjects in which these declarations were found. Using-declarations are replaced by the members they represent and type declarations, including injected-class-names are replaced by the types they represent. If C is the class in whose scope the name was used, C is examined first. If the list of declarations in C is empty, lookup set is built for each of its direct bases Bi (recursively applying these rules if Bi has its own bases). Once built, the lookup sets for the direct bases are merged into the lookup set in C as follows:

  • if the set of declarations in Bi is empty, it is discarded
  • if the lookup set of C built so far is empty, it is replaced by the lookup set of Bi
  • if every subobject in the lookup set of Bi is a base of at least one of the subobjects already added to the lookup set of C, the lookup set of Bi is discarded.
  • if every subobject already added to the lookup set of C is a base of at least one subobject in the lookup set of Bi, then the lookup set of C is discarded and replaced with the lookup set of Bi
  • otherwise, if the declaration sets in Bi and in C are different, the result is an ambiguous merge: the new lookup set of C has an invalid declaration and a union of the subobjects ealier merged into C and introduced from Bi. This invalid lookup set may not be an error if it is discarded later.
  • otherwise, the new lookup set of C has the shared declaration sets and the union of the subobjects ealier merged into C and introduced from Bi
struct X { void f(); };
struct B1: virtual X { void f(); };
struct B2: virtual X {};
struct D : B1, B2 {
void foo() {
X::f(); // OK, calls X::f (qualified lookup)
f(); // OK, calls B1::f (unqualified lookup)
// C++98 rules: B1::f hides X::f, so even though X::f can be reached from D
// through B2, it is not found by name lookup from D.
// C++11 rules: lookup set for f in D finds nothing, proceeds to bases
// lookup set for f in B1 finds B1::f, and is completed
// merge replaces the empty set, now lookup set for f in C has B1::f in B1
// lookup set for f in B2 finds nothing, proceeds to bases
// lookup for f in X finds X::f
// merge replaces the empty set, now lookup set for f in B2 has X::f in X
// merge into C finds that every subobject (X) in the lookup set in B2 is a base
// of every subobject (B1) already merged, so the B2 set is discareded
// C is left with just B1::f found in B1
// (if struct D : B2, B1 was used, then the last merge would *replace* C's
// so far merged X::f in X because every subobject already added to C (that is X)
// would be a base of at least one subobject in the new set (B1), the end
// result would be the same: lookup set in C holds just B1::f found in B1)
}
};

虚拟继承(钻石型继承)

struct V { int v; };
struct A {
int a;
static int s;
enum { e };
};
struct B : A, virtual V { };
struct C : A, virtual V { };
struct D : B, C { }; void f(D& pd) {
++pd.v; // OK: only one v because only one virtual base subobject
++pd.s; // OK: only one static A::s, even though found in B and in C
int i = pd.e; // OK: only one enumerator A::e, even though found in B and C
++pd.a; // error, ambiguous: A::a in B and A::a in C
}

Friend function definition

For a name used in a friend function definition inside the body of the class that is granting friendship, unqualified name lookup proceeds the same way as for a member function.

For a name used in a friend function which is defined outside the body of a class, unqualified name lookup proceeds the same way as for a function in a namespace.

int i = 3; // found 3rd for f1, found 2nd for f2
struct X {
static const int i = 2; // found 2nd for f1, never found for f2
friend void f1(int x)
{
// int i; // found 1st
i = x; // finds and modifies X::i
}
friend int f2();
// static const int i = 2; // found 2nd for f1 anywhere in class scope
};
void f2(int x) {
// int i; // found 1st
i = x; // finds and modifies ::i
}

Friend function declaration

For a name used in the declaration of a friend function declaration that friends a member function from another class, if the name isn't a part of an template argument, the unqualified lookup first examines the entire scope of the member function's class.--(1)(2)

If not found in that scope(or if the name is a part of a template argument), the lookup continues as if for a member function of the class that is granting friendship

--(3)

// the class whose member functions are friended
struct A {
typedef int AT;
void f1(AT);
void f2(float);
template <class T> void f3();
}; // the class that is granting friendship
struct B {
typedef char AT;
typedef float BT;
friend void A::f1(AT); (1) // lookup for AT finds A::AT
friend void A::f2(BT); (2) // lookup for BT finds B::BT
friend void A::f3<AT>(); (3) // lookup for AT finds B::AT
};

Default argument

For a name used in a default argument in a function declaration, or name used in the expression part of a member-initializer of a constructor, the function parameter names are found first, before the enclosing block, class or namespace scopes are examined:

class X {
int a, b, i, j;
public:
const int& r;
X(int i): r(a), // initializes X::r to refer to X::a
b(i), // initializes X::b to the value of the parameter i
i(i), // initializes X::i to the value of the parameter i
j(this->i) // initializes X::j to the value of X::i
{ }
} int a;
int f(int a, int b = a); // error: lookup for a finds the parameter a, not ::a
// and parameters are not allowed as default arguments

Static data member definition

For a name used in the definition of a static data member, lookup proceeds the same way as for a name used in the definition of a member function.

struct X {
static int x;
static const int n = 1; // found 1st
};
int n = 2; // found 2nd.
int X::x = n; // finds X::n, sets X::x to 1, not 2
// n的查找首先同级别的scope中查找
// 同级别的意思是X::x为X的scope,那么n也在X的scope中查找

Enumerator declaration

For a name used in the initializer part of the enumeration declaration, previously declaration enumerators in the same enumeration are found first, before the unqualified name lookup proceeds to examined the enclosing block, class or namespace scope.

const int RED = 7;
enum class color {
RED,
GREEN = RED+2, // RED finds color::RED, not ::RED, so GREEN = 2
BLUE = ::RED+4 // qualified lookup finds ::RED, BLUE = 11
};

Catch clause of a function-try block

For a name used in the catch-clause of a function-try-block, lookup proceeds as if for a name used in the very beginning of the outermost block of the function body (in particular, function parameters are visible, but names declared in that outermost block are not)

int n = 3; // found 3rd
int f(int n = 2) // found 2nd
try {
int n = -1; // never found
} catch(...) {
// int n = 1; // found 1st
assert(n == 2); // loookup for n finds function parameter f
throw;
}
Note: lookup sequence:Catch -> function parameter -> global scope

Overloaded operator

For an operator used in expression(e.g., operator+ used in a+b), the lookup rules are slightly different from the operator used in an explicit function-call expression such as operator+(a,b): when parsing an expression, two separate

lookups are performed: for the non-member operator overloads and for the member operator overloads(for the operators where both forms are permitted).

Those sets are then merged with the built-in operator overloads on equal grounds as described in overload resolution.If explicit function call syntax is used, regular unqualified name lookup is performed:

perator+(a,a)只在scope of struct B中查找,a + a会首先在scope of struct B中查找,然后再global namespace中查找,由overload resolution决定调用哪一个
struct A {};
void operator+(A, A); // user-defined non-member operator+ struct B {
void operator+(B); // user-defined member operator+
void f ();
}; A a; void B::f() // definition of a member function of B
{
operator+(a,a); // error: regular name lookup from a member function
// finds the declaration of operator+ in the scope of B
// and stops there, never reaching the global scope
a + a; // OK: member lookup finds B::operator+, non-member lookup
// finds ::operator+(A,A), overload resolution selects ::operator+(A,A)
}

Template definition(omitted)

For a non-dependent name used in a template definition, unqualified name lookup takes place when the template definition is examined.The binding to the declarations made at that point is not affected by declarations visible at the point of instantiation.

For a dependent name used in a template definition, the lookup is postponed until the template argument are known, at which time ADL examines function declarations with external linkage(until C++11)hat are visible from the template definition context as well as in the template instantiation context, while non-ADL lookup only examines function declaration with external linkage(until C++11) that are visible from the template definition context(in other words, adding a new function declaration after template definition does not make it visible except via ADL).

The behavior is undefined if there is a better match with external linkage in the namespaces examined by the ADL lookup, declared in some other translation unit, or if the lookup would have been ambiguous if those translation units were examined.

In any case, if a base class depends on a template parameter, its scope is not examined by unqualified name lookup (neither at the point of definition nor at the point of instantiation).

void f(char); // first declaration of f

template<class T>
void g(T t) {
f(1); // non-dependent name: lookup finds ::f(char) and binds it now
f(T(1)); // dependent name: lookup postponed
f(t); // dependent name: lookup postponed
// dd++; // non-dependent name: lookup finds no declaration
} enum E { e };
void f(E); // second declaration of f
void f(int); // third declaration of f
double dd; void h() {
g(e); // instantiates g<E>, at which point
// the second and the third uses of the name 'f'
// are looked up and find ::f(char) (by lookup) and ::f(E) (by ADL)
// then overload resolution chooses ::f(E).
// This calls f(char), then f(E) twice
g(32); // instantiates g<int>, at which point
// the second and the third uses of the name 'f'
// are looked up and find ::f(char) only
// then overload resolution chooses ::f(char)
// This calls f(char) three times
} typedef double A;
template<class T> class B {
typedef int A;
};
template<class T> struct X : B<T> {
A a; // lookup for A finds ::A (double), not B<T>::A
};

Unqualified 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. note: declarations in dependent base ‘std::basic_ios<char>’ are not found by unqualified lookup

    错误信息如题所示. 修改前: template< typename _CharT, typename _Traits = std::char_traits<_CharT> > ...

  6. Qualified name lookup

    Qualified name lookup Qualified name lookup Enumerations Class members Namespace members Unqualified ...

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

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

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

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

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

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

随机推荐

  1. HDOJ-ACM Steps

    在这里放几道Steps里的题目把. find your present (2) Time Limit: 1000/2000 MS (Java/Others) Memory Limit: 32768/1 ...

  2. perspective结合transform的3D效果

    http://css-tricks.com/almanac/properties/p/perspective/ 链接中讲了 perspective的两种用法及比较: 1.perspective:100 ...

  3. 类型萃取(type traits)

    1. 类型萃取的作用 类型萃取使用模板技术来萃取类型(包含自定义类型和内置类型)的某些特性,用以判断该类型是否含有某些特性,从而在泛型算法中来对该类型进行特殊的处理用来提高效率或者其他.例如:在STL ...

  4. Objective-c (多输入参数的方法)

    一个方法可能具有多个输入参数.在头文件中,可以定义带有多个输入参数的方法: - (void)setIntX:(int)n andSetIntY:(int)d 下面通过一个例子来说明它的具体用法: #i ...

  5. JavaSE_ Java基础 总目录(1~6)

    JavaSE学习总结第01天_Java概述01.01 计算机概述01.02 计算机硬件和软件概述01.03 软件开发和计算机语言概述01.04 人机交互01.05 键盘功能键和快捷键01.06 如何打 ...

  6. mysql 锁表查询及其处理

    1.show OPEN TABLES where In_use > 0; 2.show processlist; 3.kill thread_id; 其中 thread_id为processli ...

  7. Android 手机上安装并运行 Ubuntu 12.04

    ubuntu.sh脚本的原地址变动了,导致下载不了,现在更新了网盘地址.小技巧:遇到一些下载失效的时候可以试一试p2p下载工具(如 easyMule.迅雷等)试一试,说不定有人分享过~* —————— ...

  8. hdu 2874Connections between cities LCA

    题目链接 给n个城市, m条边, q个询问, 每个询问, 输出城市a和b的最短距离, 如果不联通, 输出not connected. 用并查集判联通, 如果不连通, 那么两个联通块之间加一条权值很大的 ...

  9. selenium 学习笔记 ---新手学习记录(8) 问题总结(java)

    1.获取执行js代码后的返回值 //获取滚动距离 String jl="return $('#chapterul li').height();"; Long jlhq=(Long) ...

  10. freebsd

    #cd /usr/ports/devel/binutils && make install