我是靠谱客的博主 大方百褶裙,最近开发中收集的这篇文章主要介绍Name lookup,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Name lookup

  • Types of lookup
    • Argument-dependent lookup
    • Template argument deduction
    • overload resolution

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
    • (which, for function names, includes Argument-dependent 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.

#include <iostream>
template<typename T>
void f(T s)
{
std::cout << s << 'n';
}
int main()
{
f<double>(1);
// instantiates and calls f<double>(double)
f<>('a');
// instantiates and calls f<char>(char)
f(7);
// instantiates and calls f<int>(int)
void (*ptr)(std::string) = f; // instantiates f<string>(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 ) ; (since C++11)
extern template return-type name ( parameter-list ) ; (since C++11)

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.

转载于:https://www.cnblogs.com/Wojoin/p/5168890.html

最后

以上就是大方百褶裙为你收集整理的Name lookup的全部内容,希望文章能够帮你解决Name lookup所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部