Name lookup

Name lookup is the procedure by which a name, when encountered in a program, is associated with the declaration that introduced it.

For function names, name lookup can associate multiple declarations with the same name, and may obtain additional declarations from argument-dependent lookup.

Template argument deduction may also apply, and the set of declarations is passed to overload resolution, which selects the declaration that will be used.

Member access rules, if applicable, are considered only after name lookup and overload resolution.

For all other names (variables, namespaces, classes, etc), name lookup must produce a single declaration in order for the program to compile.

For example, to compile std::cout << std::endl;, the compiler performs:

  • unqualified name lookup for the name std, which finds the declaration of namespace std in the header <iostream>
  • qualified name lookup for the name cout, which finds a variable declaration in the namespace std
  • qualified name lookup for the name endl, which finds a function template declaration in the namespace std
  • argument-dependent lookup for the name operator <<, which finds multiple function template declarations in the namespace std

Types of lookup

If the name appear immediately to the right the scope resolution operator :: or possible after :: followed by the disambiguating keyword template,see

  • Qualified name lookup.

    Otherwise, see
  • Unqualified name lookup

####Argument-dependent lookup
Argument-dependent lookup, also known as ADL, or Koenig lookup, is the set of rules for looking up the unqualified function names in function-call expressions, including implicit function calls to overloaded operators.

Examples:

namespace A {
struct X;
struct Y;
void f(int);
void g(X);
} namespace B {
void f(int i) {
f(i); // calls B::f (endless recursion)
}
void g(A::X x) {
g(x); // Error: ambiguous between B::g (ordinary lookup)
// and A::g (argument-dependent lookup)
// The programmer must explicitly qualify the call
// with the appropriate namespace name to get the g() he wants. }
void h(A::Y y) {
h(y); // calls B::h (endless recursion): ADL examines the A namespace
// but finds no A::h, so only B::h from ordinary lookup is used
}
}

In short, the meaning of code in namespace B is being affected by a function declared in the completely separate namespace A, even though B has done nothing but simply mention a type found in A and there's nary a "using" in sight!

What this means is that namespaces aren't quite as independent as people originally thought. Don't start decrying namespaces just yet, though; namespaces are still pretty independent and they fit their intended uses to a T. The purpose of this GotW is just to point out one of the (rare) cases where namespaces aren't quite hermetically sealed... and, in fact, where they should not be hermetically sealed, as the "further reading" shows.

Example from http://www.gotw.ca/gotw/030.htm

There's a little more to it, but that's essentially it. Here's an example, right out of the standard:

    namespace NS {
class T { };
void f(T);
} NS::T parm;
int main() {
f(parm); // OK, calls NS::f
}

I won't delve here into the reasons why Koenig lookup is a Good Thing (if you want to stretch your imagination, replace "NS" with "std", "T" with "string", and "f" with "operator<<" and consider the ramifications).

See the "further reading" at the end for much more on Koenig lookup and its implications for namespace isolation and analyzing class dependencies. Suffice it to say that Koenig lookup is indeed a Good Thing, and that you should be aware of how it works because it can sometimes affect the code you write.

简而言之,函数调用时,在选择正确的函数时根据参数来决定,如果参数属于另一个Namespace(例子中的NS),则该函数优先在该Namespace中查找该函数(比如std::cout << "Test";),若在Namespace中没有找到,则在本身的命名空间中查找。

###Template argument deduction
####Implicit instantiation
When code refers to a function in context that require the function definition to exist, and this particular function has not been explicit instantiated, implicit instantiation occurs. **The list of template argument does not have to be supplied if it can be deduced from context.**
```cpp
#include

template

void f(T s)

{

std::cout << s << '\n';

}

int main()

{

f(1); // instantiates and calls f(double)

f<>('a'); // instantiates and calls f(char)

f(7); // instantiates and calls f(int)

void (*ptr)(std::string) = f; // instantiates f(string)

}

> Note: omitting <> entirely allows overload resolution to examine both template and non-> template overloads.

####Explicit instantiation
`template` *return-type name* **<** *argument-list* **>** **(** *parameter-list* **)** ;
`template` *return-type name* **(** *parameter-list* **)** ;
`extern template` *return-type name* **<** *argument-list* **>** **(** *parameter-list* **)** ; <font color=green> (since C++11)</font>
`extern template` *return-type name* **(** *parameter-list* **)** ; <font color=green> (since C++11)</font>
```cpp
template<typename T>
void f(T s)
{
std::cout << s << '\n';
} template void f<double>(double); // instantiates f<double>(double),explicit
template void f<>(char); // instantiates f<char>(char), template argument deduced,implicit
template void f(int); // instantiates f<int>(int), template argument deduced,implicit

Template argument deduction(Deducing argument from parameter)

In order to instantiate a function template, every template argument must be known, but not every template argument has to be specified. When possible, the compiler will deduce the missing template arguments from the function arguments. This occurs when a function call is attempted and when an address of a function template is taken.

This occurs when a function call is attempted and when an address of a function template is taken.

template<typename To, typename From> To convert(From f);

void g(double d)
{
// double -> int
int i = convert<int>(d); // calls convert<int, double>(double)
// double -> char
char c = convert<char>(d); // calls convert<char, double>(double)
// an address of function template is taken
int (*ptr)(float) = convert; // instantiates convert<int, float>(float)
}

This mechanism makes it possible to use template operators, since there is no syntax to specify template arguments for an operator other than by re-writing it as a function call expression.

#include <iostream>
int main()
{
std::cout << "Hello, world" << std::endl;
// operator<< is looked up via ADL as std::operator<<,
// then deduced to operator<<<char, std::char_traits<char>> both times
// std::endl is deduced to &std::endl<char, std::char_traits<char>>
}

Template argument deduction takes place after the function template name lookup (which may involve argument-dependent lookup) and before overload resolution.

Template name lookup, Template argument deduction, overload resolution takes palce time sequence:

Template name lookup <= Template argument deduction < overload resolution

Overload resolution

In order to compile a function call, the compiler must first perform name lookup, which, for functions, may involve argument-dependent lookup, and for function templates may be followed by template argument deduction. If these steps produce more than one candidate function, then overload resolution is performed to select the function that will actually be called.

In general, the candidate function whose parameters match the arguments most closely is the one that is called.

Examples:

void Fcn(const int*, short); // overload #1
void Fcn(int*, int); // overload #2
int i;
short s = 0;
void f() {
Fcn(&i, 1L); // 1st argument: &i -> int* is better than &i -> const int*
// 2nd argument: 1L -> short and 1L -> int are equivalent
// calls Fcn(int*, int) Fcn(&i,'c'); // 1st argument: &i -> int* is better than &i -> const int*
// 2nd argument: 'c' -> int is better than 'c' -> short
// calls Fcn(int*, int) Fcn(&i, s); // 1st argument: &i -> int* is better than &i -> const int*
// 2nd argument: s -> short is better than s -> int
// no winner, compilation error
}

SeeOverload Resolution for more detail.

You will read more about overload resolution in future.

Name lookup的更多相关文章

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

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

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

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

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

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

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

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

  5. Lookup component 用法

    Lookup component 类似于Tsql的join子句, select a.* ,b.* from dbo.tis a left join dbo. tdes b on a.code=b.co ...

  6. [SharePoint]javascript client object model 获取lookup 类型的field的值,包括user类型(单人或者多人)的值。how to get the multiple user type/lookup type field value by Javascript client object model

    1. how to get value var context = new SP.ClientContext.get_current(); var web = context.get_web(); v ...

  7. [SharePoint 2010] Modify lookup mapping with PowerShell

    SharePoint支持将列表保存成列表模板,但当列表包含Lookup字段时,通过模板创建的列表会丢失Lookup字段的信息. 通过PowerShell,可以修改Lookup字段的xml内容. Fun ...

  8. Informatica Lookup Transformation组件的Connect 与Unconnected类型用法

    Informatica Lookup Transformation组件的Connect 与Unconnected类型用法及区别:下面是通一个Lookup在不同Mapping中的使用: 1. Conne ...

  9. AX 2012 两种lookup 的显示方式

    第一种:只能单选的lookup: 代码: public void BusinessUnitLookup(FormStringControl _formstrcontroll) { //OMOperat ...

  10. 创建一个List获取数据的lookup

    第一步,在类:syslookup中新建方法 public static client void lookupList(FormStringControl _formStringControl, Lis ...

随机推荐

  1. jQuery 插件入门

    先看http://www.cnblogs.com/lideng/p/3605551.html http://www.cnblogs.com/xcj26/p/3345556.html (非常细致  很多 ...

  2. Linux系统管理员:不要害怕升级内核

    Linux系统管理员平时很重要的一项工作就是负责系统内核升级.做好系统内核的升级工作,对于Linux系 统的稳定性具有至关重要的作用.但是很少有人敢贸然的对Linux系统的内核进行升级,担心会影响现有 ...

  3. 转:angular的decorator方法

    AngularJS实例 – 装饰$log 在AngularJS中,我们可以使用Angular内置或者自定义的services,在应用的各个部分之间分享数据和方法.假设你已经定义了一个service,但 ...

  4. java MemCachedClient遍历memcache中所有的key

    在java memcached client documentation中没有提共遍历memcache所有key的方法.但是提供了两个方法statsItems和statsCacheDump,通过sta ...

  5. oracle 11g RAC Grid Infrastructure

    grid infrastructure 软件介质下载: http://www.oracle.com/technetwork/database/database-technologies/cluster ...

  6. PHP计划任务:如何使用Linux的Crontab执行PHP脚本

    我们的PHP程序有时候需要定时执行,我们可以使用ignore_user_abort函数或是在页面放置js让用户帮我们实现.但这两种方法都不太可靠,不稳定.我们可以借助Linux的Crontab工具来稳 ...

  7. Java程序栈信息文件中的秘密(五)

    最近发现在使用jstack工具在导出Java应用的线程栈时有一个小小的窍门,比如Linux环境上有一个用户为appuser,假如以这个用户启动了一个Java进程B,如果想要导出进程B的线程栈,则必须切 ...

  8. [置顶] .NET下枚举类型的Save和Load分析

    今天在写代码的时候,心血来潮对原来的字符串保存状态位的方式很不满意,对于代码里出现了 state == "1" 这样的状态判断很是不爽.那么理想中的判断是怎样的呢?很简单如你所想枚 ...

  9. Linux进程间通信总结

    刚请完婚假,请假期间做了些技术总结,其中一个就是Linux进程间通信方式的总结. Linux提供了多种进程间通信的方式,列举如下: PIPE(管道) FIFO(先进先出,也称为有名管道) domain ...

  10. SERVLET API 中 forward() 与 redirect()的区别?

    答:前者仅是容器中控制权的转向, 在客户端浏览器地址栏中不会显示出转向后的地址: 后者则是完全的跳转, 浏览器将会得到跳转的地址, 并重新发送请求链接. 这样, 从浏览器的地址栏中可以看到跳转后的链接 ...