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.mzph.cn/pingmian/62088.shtml

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

相关文章

低功耗墒情监测站产品详解 如何助力高标准农田项目发展

一、产品概述 低功耗墒情监测站是一款集成了传感、无线通信、处理与控制等物联网技术的先进设备。它利用高精度传感器实时测量土壤墒情&#xff08;即土壤水分含量&#xff09;&#xff0c;并通过物联网技术将数据传输至云平台。这一创新设计无需铺设专门的通信线路&#xff0c…

VM+Ubuntu18.04+XSHELL+VSCode环境配置

前段时间换了新电脑&#xff0c;准备安装Linux学习环境&#xff1a;VM虚拟机、Ubuntu18.04操作系统、XSHELL、XFTP远程连接软件、VSCode编辑器等&#xff0c;打算把安装过程记录一下。 1. 虚拟机介绍 为什么要用虚拟机&#xff1f; 想学习Linux操作系统&#xff0c;一般有3种…

《Opencv》基础操作<1>

目录 一、Opencv简介 主要特点&#xff1a; 应用领域&#xff1a; 二、基础操作 1、模块导入 2、图片的读取和显示 &#xff08;1&#xff09;、读取 &#xff08;2&#xff09;、显示 3、 图片的保存 4、获取图像的基本属性 5、图像转灰度图 6、图像的截取 7、图…

【Android】ARouter的使用及源码解析

文章目录 简介介绍作用 原理关系 使用添加依赖和配置初始化SDK添加注解在目标界面跳转界面不带参跳转界面含参处理返回结果 源码基本流程getInstance()build()navigation()_navigation()Warehouse ARouter初始化init帮助类根帮助类组帮助类 completion 总结 简介 介绍 ARouter…

国内首家! 阿里云人工智能平台 PAI 通过 ITU 国际标准测评

近日&#xff0c;阿里云人工智能平台 PAI 顺利通过中国信通院组织的 ITU-T AICP-GA&#xff08;Technical Specification for Artificial Intelligence Cloud Platform&#xff1a;General Architecture&#xff09;国际标准和《智算工程平台能力要求》国内标准一致性测评&…

SpringBoot文件上传之秒传、断点续传、分片上传

一 文件上传的常见场景 在日常开发中&#xff0c;文件上传的场景多种多样。比如&#xff0c;在线教育平台上的视频资源上传&#xff0c;社交平台上的图片分享&#xff0c;以及企业内部的知识文档管理等。这些场景对文件上传的要求也各不相同&#xff0c;有的追求速度&#xff…

力扣 最长回文字串-5

最长回文字串-5 //双指针&#xff0c;暴力解法 class Solution { public:bool is(string s, int l, int r) // 判断是否为回文{while (l < r) {if (s[l] ! s[r]) {return false;}l;r--;}return true;}string longestPalindrome(string s) {int Max 0;//用来判断找出最长字…

【算法】快速求出 n 最低位的 1

Leetcode 2438. 二的幂数组中查询范围内的乘积 先展示算法具体实现 while (n) {int lowbit n & (-n);powers.push_back(lowbit);n ^ lowbit; }这段代码的核心是通过 n & (-n) 计算出 n 的 最低位的 1&#xff08;即最右边的 1&#xff09; -n 是 n 的二进制补码表…

数据抽取平台pydatax使用案例---11个库项目使用

数据抽取平台pydatax&#xff0c;前期项目做过介绍&#xff1a; 1&#xff0c;数据抽取平台pydatax介绍--实现和项目使用 项目2&#xff1a; 客户有9个分公司&#xff0c;用的ERP有9套&#xff0c;有9个库&#xff0c;不同版本&#xff0c;抽取的同一个表字段长度有不一样&…

.NET9 - Swagger平替Scalar详解(四)

书接上回&#xff0c;上一章介绍了Swagger代替品Scalar&#xff0c;在使用中遇到不少问题&#xff0c;今天单独分享一下之前Swagger中常用的功能如何在Scalar中使用。 下面我们将围绕文档版本说明、接口分类、接口描述、参数描述、枚举类型、文件上传、JWT认证等方面详细讲解。…

shiny动态生成颜色选择器并将其用于绘图

在 Shiny 中使用 uiOutput 和 renderUI 动态生成 UI 控件是一种灵活的方法。结合 uiOutput(ns("colorSelectors")) 的用法&#xff0c;可以实现动态生成颜色选择器&#xff0c;并响应用户选择进行绘图或更新显示。 代码 library(shiny) library(colourpicker)# UI …

【单点知识】基于PyTorch进行模型部署

文章目录 0. 前言1. 模型导出1.1 TorchScript1.1.1 使用 torch.jit.trace1.1.2 使用 torch.jit.script 1.2 ONNX1.2.1 导出为 ONNX 格式 1.3 导出后的模型加载1.3.1 加载 TorchScript 模型1.3.2 加载 ONNX 模型 2. 模型优化2.1 模型量化2.2 模型剪枝 3. 服务化部署3.1 Flask 部…

‌Kotlin中的?.和!!主要区别

目录 1、?.和!!介绍 2、使用场景和最佳实践 3、代码示例和解释 1、?.和!!介绍 ‌Kotlin中的?.和!!主要区别在于它们对空指针的处理方式。‌ ‌?.&#xff08;安全调用操作符&#xff09;‌&#xff1a;当变量可能为null时&#xff0c;使用?.可以安全地调用其方法或属性…

java基础知识(常用类)

目录 一、包装类(Wrapper) (1)包装类与基本数据的转换 (2)包装类与String类型的转换 (3)Integer类和Character类常用的方法 二、String类 (1)String类介绍 1)String 对象用于保存字符串,也就是一组字符序列 2)字符串常量对象是用双引号括起的字符序列。例如:&quo…

《Hello YOLOv8从入门到精通》5,颈部网络(Neck)结构、核心源码和参数调优

YOLOv8的颈部网络&#xff08;Neck&#xff09;是目标检测模型中的关键组成部分&#xff0c;它位于骨干网络&#xff08;Backbone&#xff09;和头部网络&#xff08;Head&#xff09;之间&#xff0c;主要负责进行特征融合和增强。 在YOLOv8中&#xff0c;颈部网络采用了先进…

C#里怎么样实现单向链表?

C#里怎么样实现单向链表? 数据结构,是程序基本表示方法。 不同的数据结构,就需要采用不同的算法。 在软件开发中,使用到的链表还是比较多的。不过,目前C#语言,基本上都类库, 所以需要自己创建链表的机会,基本不存在了。 但是作为理解原理,还是学习一下吧。 下面的例…

Servlet细节

目录 1 Servlet 是否符合线程安全&#xff1f; 2 Servlet对象的创建时间&#xff1f; 3 Servlet 绑定url 的写法 3.1 一个Servlet 可以绑定多个url 3.2 在web.xml 配置文件中 url-pattern写法 1 Servlet 是否符合线程安全&#xff1f; 答案&#xff1a;不安全 判断一个线程…

对比三种UI交互界面的方案

在嵌入式系统的显示应用领域&#xff0c;如何高效、稳定地驱动TFT LCD显示屏至关重要。当下主流方案有三种&#xff1a; 单片机控制芯片屏 &#xff0c;常见的是瑞佑系列芯片单片机串口屏&#xff0c;常见迪文和大彩单片机内建LCD驱动&#xff0c;常见比如ST32F429等 这三种各…

w~视觉~3D~合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/12538137 #SIF3D 通过两种创新的注意力机制——三元意图感知注意力&#xff08;TIA&#xff09;和场景语义一致性感知注意力&#xff08;SCA&#xff09;——来识别场景中的显著点云&#xff0c;并辅助运动轨迹和姿态的预测…

fastjson不出网打法—BCEL链

前言 众所周知fastjson公开的就三条链&#xff0c;一个是TemplatesImpl链&#xff0c;但是要求太苛刻了&#xff0c;JNDI的话需要服务器出网才行&#xff0c;BCEL链就是专门应对不出网的情况。 实验环境 fastjson1.2.4 jdk8u91 dbcp 9.0.20 什么是BCEL BCEL的全名应该是…