C++ ADL参数依赖查找

自以为作为一个C++老鸟,对C++里面各种概念应该都比较熟悉了,但是今天看书的时候又学到了一个装逼的概念ADL,本着学C++装逼装到底的精神,就把这个概念学习了一番。

ADL 的工作原理

在C++中,ADLArgument-Dependent Lookup 的缩写即参数依赖查找。它是一种在特定情况下用来查找函数或运算符的规则。

ADL 会在调用函数时,除了按照通常的作用域规则查找函数外,还会根据函数参数的命名空间类类型来查找可能的候选函数。

当你调用一个未限定作用域的函数(例如没有写 namespace:: 的函数调用),编译器会:

  • 先在调用处的普通作用域中查找函数(即通过标准的名称查找规则)。
  • 如果未找到匹配的函数,编译器会根据参数类型的命名空间类所在的命名空间,继续查找函数。
  • 编译器会优先选择参数所在命名空间中的函数,而不是全局命名空间中的同名函数。
#include <iostream>namespace MyNamespace {struct MyStruct {};void print(const MyStruct&) {std::cout << "MyNamespace::print called\n";}
}int main() {MyNamespace::MyStruct obj;// 调用未限定作用域的函数print(obj); // ADL 会查找到 MyNamespace::printreturn 0;
}

在上面的例子中,虽然没有显式写出 MyNamespace::print(obj),但由于参数 objMyNamespace::MyStruct 类型,ADL 会将 MyNamespace 纳入函数查找范围,最终找到 MyNamespace::print

ADL 与运算符重载

其实在最常见的运算符重载中已经有ADL的使用,只不过之前不知道ADL这个概念而已,看下面例子是不是很熟悉

#include <iostream>namespace Math {struct Vector {int x, y;};// 定义一个和全局 operator<< 不冲突的版本std::ostream& operator<<(std::ostream& os, const Vector& v) {os << "(" << v.x << ", " << v.y << ")";return os;}
}int main() {Math::Vector v{3, 4};// ADL 确保 operator<< 从 Math 命名空间查找到正确的定义std::cout << v << std::endl;return 0;
}

std::ostream 重载的 << 流运算符是定义在标准命名空间 std 中的,上面函数本该调用 std::operator<<(std::cout, v),但是在 Math 命名空间中,用户重载了Math::Vectoroperator<< 定义,ADL 会自动找到正确的 Math::operator<<

运算符重载是 ADL 的一个经典应用场景,因为运算符通常与自定义类型的命名空间相关联,ADL 可以确保运算符能正确地从参数的相关命名空间中找到。

ADL 和 std::swap

std::swap 是 C++ 标准库中的一个函数模板,用于交换两个对象的值。为了支持自定义类型,可以在自定义类型的命名空间中重载 swap

#include <algorithm> // std::swap
#include <iostream>namespace Custom {struct Widget {int value;
};// 定义命名空间范围的自定义 swapvoid swap(Widget& lhs, Widget& rhs) {std::swap(lhs.value, rhs.value); // 使用标准库的 swap 交换内部值std::cout << "Custom::swap called\n";}
}int main() {Custom::Widget w1{10}, w2{20};// 调用 std::swapusing std::swap;swap(w1, w2); // ADL 会查找到 Custom::swapstd::cout << "w1.value = " << w1.value << ", w2.value = " << w2.value << "\n";return 0;
}

调用 swap(w1, w2) 时,标准库的 std::swap 不适合直接处理 Custom::Widget。ADL 将根据参数 w1w2 的类型,进入 Custom 命名空间,找到 Custom::swap

ADL 和隐藏友元函数

隐藏友元函数是指通过在类中定义友元函数,但将其声明和定义放在类的内部,而不是类的外部。这种方式使得友元函数无法直接在类外部被普通的名称查找规则找到,但它可以通过 ADL 被正确查找到。隐藏友元函数的作用通常是防止全局作用域污染,限制函数的可见性,使得函数仅在需要时通过 ADL 查找到。

#include <iostream>class MyClass {
public:MyClass(int value) : value_(value) {}// 声明一个友元函数friend std::ostream& operator<<(std::ostream& os, const MyClass& obj) {os << "MyClass(" << obj.value_ << ")";return os;}private:int value_;
};int main() {MyClass obj(42);// ADL 会查找到友元函数 operator<<std::cout << obj << std::endl;// std::operator<< 不会因为友元函数的定义而被隐藏std::cout << "Test" << std::endl;return 0;
}
  • operator<< 是一个隐藏友元函数,因为它的声明和定义都在 MyClass 内部。
  • 当调用 std::cout << obj 时,ADL 会通过参数 obj 的类型(MyClass)进入 MyClass 的定义范围,并找到 operator<<
总结

上面的一些示例代码其实是日常中比较常见的稀疏平常的代码,但是之前基本上不知道里面还有ADL这一说法,相信大家了解ADL概念了,应该对之前一些稀松平常的代码有更深的理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/479671.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win10 禁止更新

一、winR 输入 regedit 二、输入注册列表路径&#xff1a; &#xff08;1&#xff09;计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings &#xff08;2&#xff09;按照格式&#xff0c;创建文件命名: FlightSettingsMaxPauseDays &#xff08;3&…

OpenAI Whisper 语音识别 模型部署及接口封装

环境配置: 一、安装依赖&#xff1a; pip install -U openai-whisper 或者&#xff0c;以下命令会从这个存储库拉取并安装最新的提交&#xff0c;以及其Python依赖项&#xff1a; pip install githttps://github.com/openai/whisper.git 二、安装ffmpeg&#xff1a; cd …

springboot视频网站系统的设计与实现(代码+数据库+LW)

摘 要 使用旧方法对视频信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在视频信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的视频网站系统管理员功…

安装QT6.8(MSVC MinGW)+QT webengine+QT5.15.2

本篇主要针对只使用过QT5的qmake&#xff0c;没有用过MSVC&#xff0c;VS的老同学。 建议一部分一部分安装&#xff0c;全部勾选安装遇到问题会中断&#xff0c;前功尽弃。 我自己需要的是QT5&#xff0c;编出的软件用在公司设备上。 QT6&#xff1a;建议也安装学习&#xf…

自动驾驶目标检测融合全貌

1、early fusion 早期融合&#xff0c;特点用到几何空间转换3d到2d或者2d到3d的转换&#xff0c;用像素找点云或者用点云找像素。 2、deep fusion 深度融合&#xff0c;也是特征级别融合&#xff0c;也叫多模态融合&#xff0c;如bevfusion范式 3、late fusion 晚融合&#x…

Microsoft Excel如何插入多行

1.打开要编辑的excel表&#xff0c;在指定位置&#xff0c;鼠标右键点击“插入”一行 2.按住shift键&#xff0c;鼠标的光标箭头会变化成如下图所示 3.一直按住shift键和鼠标左键&#xff0c;往下拖动&#xff0c;直至到插入足够的行

node.js基础学习-http模块-创建HTTP服务器、客户端(一)

http模块式Node.js内置的模块&#xff0c;用于创建和管理HTTP服务器。Node.js使用JavaScript实现&#xff0c;因此性能更好。 使用http模块创建服务器&#xff0c;我们建议使用commonjs模块规范&#xff0c;因为很多第三方的组件都使用了这种规范。当然es6写法也支持。 下面就是…

2024御网杯信息安全大赛个人赛wp(misc方向)

目录 一.信息安全大赛的通知二、编码转换1. 第一部分2. 第二部分3. 第三部分 三、1.txt四、buletooth 题目附件以及工具链接&#xff1a; 通过网盘分享的文件&#xff1a;御网杯附件 链接: https://pan.baidu.com/s/1LNA6Xz6eZodSV0Io9jGSZg 提取码: jay1 –来自百度网盘超级会…

浅谈pdfbox2.0和pdfbox3.0的运用与区别

前言 Apache PDFBox 是一个开源的Java库&#xff0c;可以用来对PDF文档做一些基本操作&#xff0c;比如实际应用中的pdf读取、写入、合并、拆分、写文字、写图片、加水印等&#xff0c;甚至还应用到了电子签章。本文逐个介绍对pdf的操作&#xff0c;以备作为后续参考使用。 一…

《解锁计算机专业宝藏:核心编程语言与学习资料全解析》

在当今数字化浪潮汹涌澎湃、技术迭代日新月异的时代&#xff0c;计算机专业宛如一座蕴藏无尽宝藏与无限机遇的神秘殿堂&#x1f3f0;。对于莘莘学子而言&#xff0c;精准掌握核心编程语言&#xff0c;并手握优质学习资料&#xff0c;恰似寻得开启这扇殿堂大门的秘钥&#xff0c…

【计算机网络】多路转接之epoll

epoll也是一种linux中的多路转接方案(epoll也是只负责IO过程中的"等") 一、epoll相关接口的使用 1.epoll_create int epoll_create(int size); ​功能&#xff1a;创建一个epoll模型 ① int size&#xff1a;没意义了 >0就行 返回值&#xff1a;返回一个文件…

「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏

本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字&#xff0c;应用会判断是否接近目标数字&#xff0c;并提供提示“高一点”或“低一点”&#xff0c;直到用户猜中目标数字。这个小游戏结合状态管理和用户交互&#xff0c;是一个入门级的互动应用示例。 关键词 UI互…

Brain.js 用于浏览器的 GPU 加速神经网络

Brain.js 是一个强大的 JavaScript 库&#xff0c;它允许开发者在浏览器和 Node.js 环境中构建和训练神经网络 。这个库的目的是简化机器学习模型的集成过程&#xff0c;使得即使是没有深厚机器学习背景的开发者也能快速上手 。 概述 Brain.js 提供了易于使用的 API&#xff…

365天深度学习训练营-第P6周:VGG-16算法-Pytorch实现人脸识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文为「365天深度学习训练营」内部文章 参考本文所写记录性文章&#xff0c;请在文章开头带上「&#x1f449;声明」 &#x1f37a;要求&#xff1a; 保存训练过…

预处理指令

1.预定义符号 预定义符号是在预处理阶段处理的。 1.__FILE__ // 进⾏编译的源⽂件 2.__LINE__ // ⽂件当前的⾏号 3.__DATE__ // ⽂件被编译的⽇期 4.__TIME__ // ⽂件被编译的时间 5.__STDC__ // 如果编译器遵循 ANSI C &#xff0c;其值为 1 &#xff0c;否则未定义…

Android 12.0新增自定义HIDL问题记录

代码 流程和代码可以参考这位大佬的 https://blog.csdn.net/learnframework/article/details/134621556 主要记录发现的问题以及解决方式。 1.首先最外层的bp不要使用update-makefiles.sh 去生成 &#xff0c;基本上interface下面的文件夹都会被影响&#xff0c;可能会导致编…

(即插即用模块-Attention部分) 二十、(2021) GAA 门控轴向注意力

文章目录 1、Gated Axial-Attention2、代码实现 paper&#xff1a;Medical Transformer: Gated Axial-Attention for Medical Image Segmentation Code&#xff1a;https://github.com/jeya-maria-jose/Medical-Transformer 1、Gated Axial-Attention 论文首先分析了 ViTs 在训…

[C++ 核心编程]笔记 4.1 封装

4.1.1 封装的意义 封装是C面向对象三大特性之一 封装的意义: 将属性和行为作为一个整体&#xff0c;表现生活中的事物将属性和行为加以权限控制 封装意义一: 在设计类的时候&#xff0c;属性和行为写在一起&#xff0c;表现事物 语法: class 类名{ 访问权限: 属性 /行为 }…

韩顺平 一周学会Linux | Linux 实操篇-组管理和权限管理

一、Linux 组 1. 组基本介绍 在linux 中的每个用户必须属于一个组&#xff0c;不能独立于组外。在linux 中每个文件有所有者、所在组、其它组的概念。 2. 文件/目录 所有者 一般为文件的创建者,谁创建了该文件&#xff0c;就自然的成为该文件的所有者。 1) 查看文件所有者&…

FBX福币交易所创业板指放量大涨2.73% 谷子经济概念持续爆发

查查配分析11月27日电 27日,A股三大指数探底回升,沪指涨逾1%,创业板指涨近3%。全市成交额较上个交易日放量至1.49万亿元。 截至收盘,上证指数涨1.53%,报3309.78点;深证成指涨2.25%,报10566.10点;创业板指涨2.73%,报2208.78点。 FBX福币凭借用户友好的界面和对透明度的承诺,迅速…