C++ ADL 与 模板
什么是ADL
ADL(Argument Dependent Lookup),参数依赖查找,明确的意思是依赖参数的函数查找,即对于函数调用,不仅会依照常规的名称查找规则,还会在函数参数所在的命名空间内查找
我们常用的 std::cout << "..." 其实就是一个 ADL 的例子,std::cout,查看一下 STL 的代码,它是
std::basic_ostream<char, std::char_traits<char>>
而这个类只定义了针对算术类型和指针类型的 operator<< 并没有定义针对 const char * 的版本,使用编译器的跳转功能跳转到 << 的调用,其实是
template<class _Traits>
std::basic_ostream<char, _Traits> operator<<(std::basic_ostream<char, _Traits> &, const char *)
也就是说这个调用其实等价于:
operator<<(std::cout, "...")//注意operator<<前并没有使用std::来指定查找位置
这个对于 std::operator<< 的调用能顺利解析而不会触发 '没有与操作数匹配的操作符' 错误,正是由于ADL发挥了作用:第一个参数 std::cout 所在的命名空间 std 被加入到对 operator<< 的查找空间内,从而匹配到针对 const char * 的 operator<<
ADL+模板
当函数参数是模板时,查找空间会扩展到参数模板所在的命名空间以及模板实参的命名空间:
折叠代码
namespace space
{
struct A{};
template<typename T> struct TpA{};
template<typename T, template<typename> class Tp>
void foo(Tp<T> &){}
}
template<typename T> struct TpB{};
space::TpA<int> tai;
foo(tai);//通过TpA找到foo
TpB<space::A> tba;
foo(tba);//通过A找到foo
根据模板实参自动选择调用函数
ADL+模板很容易就能实现根据模板实参调用不同函数的功能:
折叠代码
namespace spaceA
{
struct A{};
void foo(A &){}
}
namespace spaceB
{
struct B{};
void foo(B &){}
}
...
template<typename T> void dispatch(T &value)
{
foo(value);
}
spaceA::A a;
dispatch(a);//绑定到spaceA::foo(spaceA::A &)
spaceB::B b;
dispatch(b);//绑定到spaceB::foo(spaceB::B &)
只要约定好接口,dispatch函数就能根据实例化类型来调用,可以实现松散的代码结构,并且函数的绑定在编译期进行,继承体系也能实现相同的需求,但是函数的调用是运行时解析。可以根据实际情况决定选用哪种方案。
C++ ADL 与 模板的更多相关文章
- boost::swap
boost::swap是对标准库里的std::swap的增强和泛化,为交换两个变量的值提供便捷的方法. 为了使用需包含头文件: #include <boost/swap.hpp> 原理 c ...
- c++11-17 模板核心知识(十三)—— 名称查找与ADL
名称分类 名称查找 ordinary lookup ADL (Argument-Dependent Lookup) 官网的例子 ADL的缺点 在C++中,如果编译器遇到一个名称,它会寻找这个名称代表什 ...
- C++ template —— 实例化和模板实参演绎(四)
本篇讲解实例化和模板实参演绎-------------------------------------------------------------------------------------- ...
- C++ template —— 模板中的名称(三)
第9章 模板中的名称------------------------------------------------------------------------------------------ ...
- 参数依赖查找(ADL,Argument-dependent lookup)
参数依赖查找(Argument-dependent lookup),又称 ADL 或 Koenig 查找,是一组于函数调用表达式查找非限定函数名的规则,包含对重载运算符的隐式函数调用.在通常非限定名称 ...
- C++ ADL
即在一个名称作为调用运算符的左操作数时,并且这个名字是一个无限定名称时,在无限定查找到的名字集合中额外增加的一个规则使集合范围扩大(从而可以定位到其他一些限定名称),通常是用来保证定义在不同命名空间的 ...
- c++11-17 模板核心知识(十四)—— 解析模板之依赖型模板名称(.template/->template/::template)
tokenization与parsing 解析模板之类型的依赖名称 Dependent Names of Templates Example One Example Two Example Three ...
- c++11-17 模板核心知识(十五)—— 解析模板之依赖型类型名称与typename Dependent Names of Types
模板名称的问题及解决 typename规则 C++20 typename 上篇文章c++11-17 模板核心知识(十四)-- 解析模板之依赖型模板名称 Dependent Names of Templ ...
- Jade模板引擎让你飞
写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...
- ABP入门系列(2)——通过模板创建MAP版本项目
一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...
随机推荐
- 开源一款DDS信号发生扩展板-FreakStudio多米诺系列
原文链接: FreakStudio的博客 摘要 信号发生扩展板通过SPI接口生成可调频率和幅度的正弦波.方波和三角波,频率小于1MHz.支持幅度调节,提供原始和6倍放大输出接口.配备5阶低通滤波器.噪 ...
- CUDA与Cython之BatchGather
技术背景 在前面一篇文章中,我们介绍过Cython+CUDA框架下实现一个简单的Gather算子的方法.这里演示Gather算子的升级版本实现--BatchGather算子.不过这里只是加了一个Bat ...
- Cython与CUDA之Add
技术背景 在前一篇文章中,我们介绍过使用Cython结合CUDA实现了一个Gather算子以及一个BatchGather算子.这里我们继续使用这一套方案,实现一个简单的求和函数,通过CUDA来计算数组 ...
- 分布式锁—7.Curator的分布式锁
大纲 1.Curator的可重入锁的源码 2.Curator的非可重入锁的源码 3.Curator的可重入读写锁的源码 4.Curator的MultiLock源码 5.Curator的Semaphor ...
- PPT-嵌入字体提示不可嵌入怎么办
直接将不可嵌入的字体替换为可以嵌入的字体 开始->替换->替换字体
- python 将字典转换为列表
在实现功能时,有时候有些函数适用于非字典形式 这时候就需要把字典转换为其他形式 本例主要讲解字典到列表转换 datas=[{'1':'nihao'},{'2':'very goog'}] to_lis ...
- Kubernetes 编译 kubeadm 修改证书有效期到 100 年
前言 kubeadm 生成的客户端证书在 1 年后到期.过期后,会导致服务不可用,使用过程中会出现:x509: certificate has expired or is not yet valid. ...
- oracle 添加白名单- 重启监听
由于oracle中存在白名单,有新增主机需要访问,添加白名单需要重启监听 1.添加白名单 登陆oracle主机,su - grid 切到grid用户, vi $ORACLE_HOME/network/ ...
- apisix~key-auth多消费的使用
在 APISIX 中使用 key-auth 插件实现基于密钥的认证,以下是详细的配置步骤,包括如何保存密钥和证书,以及如何将这些信息分配给客户端 A 和 B. 场景说明 服务 C 是后端服务,需要通过 ...
- static修饰成员变量的特点及static修饰成员变量内存图解-java se进阶 day01
1.static介绍 static是静态的意思,它可以用于修饰成员变量和成员方法 2.static的特点 1.被static修饰了的成员变量,可以被类中的所有对象所共享 虽然stu02没有给schoo ...