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结尾的项目,设置为启动项目: 打 ...
随机推荐
- SM系列国密算法
其中SM1.SM4.SM7.祖冲之密码(ZUC)是对称算法:SM2.SM9是非对称算法:SM3是哈希算法.目前,这些算法已广泛应用于各个领域中,期待有一天会有采用国密算法的区块链应用出现. 一.SM1 ...
- MyBatis与其使用方法讲解
ORM 在讲解Mybatis之前,我们需了解一个概念ORM(Object-Relational Mapping)对象关系映射,其是数据库与Java对象进行映射的一个技术.通过使用ORM,我们可以不用编 ...
- 从RNN、LSTM到NTM、MANN——神经网络的记忆与推理进化
从RNN.LSTM到NTM.MANN--神经网络的记忆与推理进化 一.前言:为什么要研究记忆? (温馨提示:在阅读本文之前,请确保你已经对深度学习中最基本的概念有一定的了解,例如:激活函数.多层感知机 ...
- 通过 API 将Deepseek响应流式内容输出到前端
要实现通过 API 将流式内容输出到前端,可以采用以下技术方案(以 Python 后端 + 前端 JavaScript 为例): 方案一:使用 Server-Sent Events (SSE) 这是浏 ...
- PDF转换:从Word到Excel
一.引言 在数字化的浪潮中,PDF文件格式以其稳定性和兼容性成为了信息交流的宠儿.然而,当我们需要编辑这些PDF文件时,往往会遇到各种难题.今天,我要和大家分享的,是如何将PDF文件轻松转换成Word ...
- 【VMware VCF】解决 VCF 环境中组件用户密码过期问题。
由于长时间没有启动 VCF 环境,现在在启动 SDDC Manager 组件后,UI 一直处于如下图所示的"初始化"状态.当时第一直觉就认为肯定是 VCF 环境组件的用户密码过期了 ...
- 认识webRTC
什么是 WebRTC 2010 年 5 月,谷歌收购了 Global IP Solutions(简称 GIPS),这是一家专注于 VoIP 和视频会议软件的公司,已开发出 RTC 所需的多项关键组件, ...
- VRRP+BFD实验
VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)的工作原理主要涉及多个路由器(或具备路由功能的设备)协同工作,通过VRRP报文和优先级机制来选举出一 ...
- Delphi 中拖动无边框窗口的5种方法
1.MouseMove事件中加入: // ReleaseCapture; // Perform(WM_SYSCOMMAND, $F017 , 0); 2.MouseDown事件中加入: // POST ...
- apisix~hmac-auth插件的使用
hmac-auth插件需要和 Consumer 一起使用,API 的使用者必须将密匙添加到请求头中以验证其请求,下面介绍它的主要用法 参数 algorithm 算法 默认hmac-sha256 [&q ...