参数依赖查找(ADL,Argument-dependent lookup)
参数依赖查找(Argument-dependent lookup),又称 ADL 或 Koenig 查找,是一组于函数调用表达式查找非限定函数名的规则,包含对重载运算符的隐式函数调用。在通常非限定名称查找所考虑的作用域和命名空间之外,还在其参数的命名空间中查找这些函数。
参数依赖查找使使用定义于不同命名空间的运算符可行。例如:
#include <iostream>
int main()
{
std::cout << "Test\n"; // 全局命名空间无 operator<< ,但 ADL 检验 std 命名空间,
// 因为左参数在 std 命名空间中
// 并找到 std::operator<<(std::ostream&, const char*)
operator<<(std::cout, "Test\n"); // 同上,用函数调用记法 // 然而,
std::cout << endl; // 错误: 'endl' 不声明于此命名空间。
// 此非对 endl() 的函数调用,故不应用 ADL endl(std::cout); // OK :这是函数调用: ADL 检验 std 命名空间,
// 因为 endl 的参数在 std ,并找到 std::endl (endl)(std::cout); // 错误: 'endl' 不声明于此命名空间。
// 子表达式 (endl) 不是函数调用表达式
}
细节
首先,若通常非限定查找所生成的集合含有下列任何内容,则不考虑参数依赖查找:
否则,对于每个函数调用表达式中的参数,检验其类型,以确定它将添加到查找的命名空间与类的关联集。
若类与命名空间的关联集中的任何命名空间是内联命名空间,则添加其外围命名空间到集合。
若类与命名空间的关联集中的任何命名空间直接含有内联命名空间,则添加该内联命名空间到集合。
在确定命名空间与类的关联集后,为了进一步的 ADL 处理,忽略此集中所有于类中找到的声明,除了命名空间作用域的友元函数及函数模板,陈述于后述点 2 。
以下列特殊规则,合并普通非限定查找找到的声明集合,与在 ADL 所生成关联集的所有元素中找到的声明集合
注意
因为参数依赖查找,定义于相同命名空间的非成员函数和非成员运算符被认为是该类公开接口的一部分(若它们为 ADL 所找到)[1]。
ADL 是为于泛型代码交换二个对象而建立的手法的背后理由:
using std::swap;
swap(obj1, obj2);
因为直接调用 std::swap(obj1, obj2) 不会考虑用户定义的 swap() 函数,它可能定义于与 obj1 或 obj2 类型之定义相同的空间,而仅调用非限定的 swap(obj1, obj2) 会无法调用任何函数,若不提供用户定义重载。特别是 std::iter_swap 与所有其他标准库算法在处理可交换 (Swappable) 类型时使用此手段。
名称查找规则使得在来自 std 命名空间的类型上声明运算符于全局或用户定义命名空间,例如对于 std::vector 或 std::pair 的自定义 operator+ 或 operator>> 不适于实践(除非 vector/pair 的元素类型是用户定义类型,这会添加其命名空间到 ADL )。这种运算符不会从诸如标准库算法的模板实例化查找。进一步细节见依赖名。
ADL 能找到全体定义于类或类模板内的友元函数(典型地是重载的运算符),即使它完全不在命名空间层次声明。
template<typename T>
struct number
{
number(int);
friend number gcd(number x, number y) { return ; }; // 类模板内的定义
};
// 除非提供匹配声明,否则 gcd 是此命名空间的不可见成员(除非通过 ADL )
void g() {
number<double> a(), b();
a = gcd(a,b); // 找到 gcd ,因为 number<double> 是关联类,
// 令 gcd 于其命名空间(全局命名空间)可见
// b = gcd(3,4); // 错误: gcd 不可见
}
尽管即使普通查找找不到结果,函数调用也能通过 ADL 解决,对带显示指定模板实参的函数模板调用还是要求有普通查找所能找到的模板声明(否则,它会是遇到未知名称后随小于号的语法错误)
namespace N1 {
struct S {};
template<int X> void f(S);
}
namespace N2 {
template<class T> void f(T t);
}
void g(N1::S s) {
f<>(s); // 语法错误(无限定查找找不到 f )
N1::f<>(s); // OK ,有限定查找找到模板 'f'
N2::f<>(s); // 错误: N2::f 不接收非类型模板形参
// N1::f 不能被找到,因为 ADL 仅适用于非限定名
using N2::f;
f<>(s); // OK :无限定查找现在找到 N2::f 然后 ADL 表态,
// 因为此名无限定并找到 N1::f
}
下列语境发生仅 ADL 的查找(即仅于关联的命名空间查找):
示例
struct X;
struct Y;
void f(int);
void g(X);
} namespace B {
void f(int i) {
f(i); // 调用 B::f (无限递归)
}
void g(A::X x) {
g(x); // 错误:在 B::g (普通查找)与 A::g (参数依赖查找)间歧义
}
void h(A::Y y) {
h(y); // 调用 B::h (无限递归): ADL 检验 A 命名空间
// 但找不到 A::h ,故只用来自通常查找的 B::h
}
}
参数依赖查找(ADL,Argument-dependent lookup)的更多相关文章
- Spring IOC(六)依赖查找
Spring IOC(六)依赖查找 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring BeanFactory ...
- Spring中的依赖查找和依赖注入
作者:Grey 原文地址: 语雀 博客园 依赖查找 Spring IoC 依赖查找分为以下几种方式 根据 Bean 名称查找 实时查找 延迟查找 根据 Bean 类型查找 单个 Bean 对象 集合 ...
- ApiPost自动化测试基础之:接口参数依赖的情景处理
在<ApiPost环境变量之第1课>里,我们介绍了什么是ApiPost环境变量,并如何定义.使用它. 环境变量.接口参数依赖的处理是ApiPost自动化测试的基础.本文主要讲解接口参数依赖 ...
- Spring Ioc 依赖查找
Spring ioc 有依赖查找和依赖注入,之前不太明白依赖查找是什么意思,翻了一大堆博客看了好多定义也不太清楚 ,后来看了小马哥视频,他通过代码演示,清楚地讲解了什么是 依赖查找以及几种依赖查找的方 ...
- 【Spring】IoC容器 - 依赖查找
前言 上一篇文章已经学习了[IoC的主要实现策略]有2种: 1.依赖查找 2.依赖注入 这里稍加详细的介绍一下依赖查找 1.依赖查找的方式 依赖查找的方式可以以多种维度来划分: 1.按名称/类型/注解 ...
- EXCEL查找函数之VLOOKUP,LOOKUP,HLOOKUP
VLOOKUP是纵向查询函数,VLOOKUP(lookup_value,table_array,col_index_num,range_lookup). 参数 ...
- 关于laravel5.5控制器方法参数依赖注入原理深度解析及问题修复
在laravel5.5中,可以根据控制器方法的参数类型,自动注入一个实例化对象,极大提升了编程的效率,但是相比较与Java的SpringMVC框架,功能还是有所欠缺,使用起来还是不太方便,主要体现在方 ...
- 【转】使用windeployqt.exe进行依赖查找打包
原文:https://blog.csdn.net/u011822862/article/details/52166940 Qt 官方开发环境使用的动态链接库方式,在发布生成的可执行程序时,需要复制可执 ...
- Go 包管理与依赖查找顺序
目录 1. 规则: 2. 编译时的依赖包查找机制 3.vendor vendor的层级搜索 4. modules 1. 规则: 同一目录下只能存在一个包 目录和目录下源文件的包命名可以不同 当包名与目 ...
随机推荐
- 字符约束条件的SQL注入攻击
引言 目前值得高兴的是,开发者在建立网站时,已经开始关注安全问题了——几乎每个开发者都知道SQL注入漏洞了.在本文中,我将为读者介绍另一种与SQL数据库相关的漏洞,虽然它的危害性与SQL注入不相上下, ...
- JSP -- include指令与include动作的区别
JSP -- include指令与include动作的区别 (1)格式的区别: include指令:<%@include file = "文件名"%> include动 ...
- Codeforces Round #348 (VK Cup 2016 Round 2, Div. 2 Edition) C. Little Artem and Matrix 模拟
C. Little Artem and Matrix 题目连接: http://www.codeforces.com/contest/669/problem/C Description Little ...
- Codeforces Round #245 (Div. 2) B. Balls Game 并查集
B. Balls Game Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/430/problem ...
- 数组、Set对象的互相转换
一.数组与Set对象之间的转换可以实现数组的去重(数组可重复,Set不可重复) 1. 把数组对象转换为Set对象 var arr = [1,2,3,4,5,6,7,6,6,7]; console.lo ...
- PSCollectionView瀑布流实现
[-] 一基本原理 二具体实现 相关数据结构 视图更新方式 relayoutViews方法 removeAndAddCellsIfNecessary方法 select方法 重用数据块视图机制 三使用方 ...
- 将DLL挂接到远程进程之中(远程注入)
线程的远程注入 要实现线程的远程注入必须使用Windows提供的CreateRemoteThread函数来创建一个远程线程该函数的原型如下:HANDLE CreateRemoteThread( ...
- Spring JavaConfig @Import实例
一般来说, 需要按模块或类别 分割Spring XML bean文件 成多个小文件, 使事情更容易维护和模块化. 例如, <beans xmlns="http://www.spring ...
- 第一篇 对Javascript中原型的深入理解
理解原型对象 在Javascript中不管什么时候,仅仅要创建一个新的函数,就会依据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象(这个对象的用途是包括能够有特定 ...
- 显示所有环境变量:env 或者 printenv
显示所有环境变量:env 或者 printenv