c++ 学习 笔记 之 template name lookup method:ADL

ADL: Argument-Dependent Lookup

ADL 只适用于这样的非受饰名称(unqualified names):在函数调用动作中用到的一个非成员函 式名称。如果 ordinary lookup 可找到一个成员函数名称或一个类型名称,编译器就不启动ADL。如果被调用函数的名称被写进一对小(圆)括号内,ADL 也不起作用。否则,如果名称之后跟着的是一个以小(圆)括号括起的自变量算式列(argument expressions list),ADL 就会在「与所有 call arguments 类型相关联」的每一个 namespace 和 class 中查询该名称。如果后面跟的是<>切<>不是类型 那也不启动ADL(这里有点疑问). 所 谓「相关联的 namespaces 和 classes」的精确定义将在稍后给出,但你可以直观认为,它们与给 定之类型有十分直接的关系。假设给定的类型是个指针,指向 class X,编译器便认为X以及X隶属的所有 classes 和 namespaces 都与该指针类型相关联(associated)。下面是「与 call arguments 类型相关联之 namespaces 集和 classes 集」的精确定义:

下面是「与 call arguments 类型相关联之 namespaces 集和 classes 集」的精确定义:

  对内建类型而言:空集合。
  对 pointer 类型和 array 类型而言:基础构成类型(underlying type;亦即 pointer 所指类型或
array
元素类型)。
  对 enum 类型而言:声明所在之 namespace。如果其成员是 classes,那么圈封类别(enclosing
class)就是其关联类别(associated class)。
  对 class(含 union)类型而言:「相关联之 class 集」包括(1) class 或 union 自身、(2) 其
圈封 类别(enclosing class)、以及 (3) 任何直接或间接的 base classes。「相关联之 namespace
集」 则包括所有「相关联之 classes」声明所在的 namespaces。如果我们所讨论的这个 class 是
个 class template 具现体,那么所谓「相关联之 class 集」和「相关联之 namespace 集」就还包
括 (1) 每一个 template type argument 类型,以及 (2) 每一个 template template arguments 声明所
在的classes 和 namespaces。
  对 function 类型而言:所有「与参数类型和回返值类型相关联」的 classes 和 namespaces。
  对pointer-to-member-of-class-X 类型而言:所有「与X相关联」以及「与被指向之成员相关

联」的 classes 和 namespaces。如果我们所讨论的是个 pointer-to-member-function 类型,
那么就还包括所有「与参数和回返值相关联」的 classes 和 namespaces。
ADL 会在所有「相关联的namespaces」中查询名称,就像该名称被所有这些namespaces修饰过一
样(只不过略去 using 指令罢了)。下面例子展示了ADL过程:
// details/adl.cpp
#include <iostream>
namespace X {
template<typename T> void f(T);
}

namespace N {
using namespace X;
enum E { e1 };
void f(E) {
std::cout << "N::f(N::E) called" << std::endl;
}
}
void f(int)
{
std::cout << "::f(int) called" << std::endl;
}
int main()
{
::f(N::e1); // 受饰(qualified)函数名称:不使用 ADL。
f(N::e1); // ordinary lookup 找到::f,而 ADL 找到 N::f(),编译器会优先考虑后者
}
注意这个例子,当编译器动用 ADL 机制时,namespace N 中的using 指令被忽略。因此main()中
的 f()不会被编译器认为是对 X::f()调用。



ADL 和 Explicit Template Arguments(明 确 模板引 数)
考虑下面例子:
namespace N {
class X {
...
};
template<int I> void select(X*);
}
void g (N::X* xp)
{
select<3>(xp); // 错误:ADL 不适用
}
此例之中,我们可能希望编译器看到 select<3>(xp)时透过 ADL 找到 template select()。
但 情况并非如此,只有在确认 <3> 是个 template argument list 时,编译器才能确认 xp 是一个
function call argumen 。反过来说,只有当编译器发现 select()是个 template,它才能确认 <3>是个 template
argument list 。这是个「先 有 鸡 还 是先有蛋」的问题 ;这个算式只能被解析( parsed )
为 (select<3)>(xp),而这毫无意义。 编译器 不能决定 select()是个 template的 原因 是 :在 function g() 内 它对 namespace 一无所知 ,所以它不能决定select 是不是模板 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值