C++ ADL参数依赖查找

news2024/11/28 15:43:31

自以为作为一个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::print
    return 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;
};

    // 定义命名空间范围的自定义 swap
    void 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::swap
    using std::swap;
    swap(w1, w2); // ADL 会查找到 Custom::swap

    std::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.coloradmin.cn/o/2249158.html

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

相关文章

数字图像处理(9):VGA接口及其时序

&#xff08;1&#xff09;特点&#xff1a;成本低、结构简单、应用灵活 VGA接口需要五个信号&#xff1a;R、G、B、Hsync、Vsync &#xff08;2&#xff09;VGA的工作原理&#xff1a; 设定一个高速时钟信号&#xff08;像素时钟&#xff09;来控制每个像素的传输速率&#…

111. UE5 GAS RPG 实现角色技能和场景状态保存到存档

实现角色的技能存档保存和加载 首先&#xff0c;我们在LoadScreenSaveGame.h文件里&#xff0c;增加一个结构体&#xff0c;用于存储技能相关的所有信息 //存储技能的相关信息结构体 USTRUCT(BlueprintType) struct FSavedAbility {GENERATED_BODY()//需要存储的技能UPROPERT…

【jmeter】服务器使用jmeter压力测试(从安装到简单压测示例)

一、服务器上安装jmeter 1、官方下载地址&#xff0c;https://jmeter.apache.org/download_jmeter.cgi 2、服务器上用wget下载 # 更新系统 sudo yum update -y# 安装 wget 以便下载 JMeter sudo yum install wget -y# 下载 JMeter 压缩包&#xff08;使用 JMeter 官方网站的最…

图像算法在生物医药领域的应用

摘要&#xff1a; 随着科技的飞速发展&#xff0c;图像算法在生物医药领域的应用日益广泛且深入。本文详细阐述了图像算法在生物医药多个方面的应用&#xff0c;包括医学影像诊断、病理图像分析、药物研发、细胞图像研究以及生物医学工程等。通过对这些应用的探讨&#xff0c;展…

注意力(Attention)机制详解(附代码)

Attention机制是深度学习中的一种技术&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;和计算机视觉领域中得到了广泛的应用。它的核心思想是模仿人类的注意力机制&#xff0c;即人类在处理信息时会集中注意力在某些关键部分上&#xff0c;而忽略其他不那么重要的…

Jmeter测试nginx部署的静态网页最大在线人数

一、下载Jmeter apache-jmeter-5.4.3.tar资源-CSDN文库 解压之后&#xff0c;双击ApacheJMeter.jar,即可打开 二、测试最大在线人数 1、plugins-manager下载安装 起初刚解压的jmeter里面没有插件管理这个选项 去官网下载&#xff1a;Install :: JMeter-Plugins.org 将下载j…

【深度学习|目标跟踪】StrongSort 详解(以及StrongSort++)

StrongSort详解 1、论文及源码2、DeepSort回顾3、StrongSort的EMA4、StrongSort的NSA Kalman5、StrongSort的MC6、StrongSort的BOT特征提取器7、StrongSort的AFLink8、未完待续 1、论文及源码 论文地址&#xff1a;https://arxiv.org/pdf/2202.13514 源码地址&#xff1a;https…

Scala关于成绩的常规操作

score.txt中的数据&#xff1a; 姓名&#xff0c;语文&#xff0c;数学&#xff0c;英语 张伟&#xff0c;87&#xff0c;92&#xff0c;88 李娜&#xff0c;90&#xff0c;85&#xff0c;95 王强&#xff0c;78&#xff0c;90&#xff0c;82 赵敏&#xff0c;92&#xff0c;8…

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

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

草图大师2020安装教程附安装包下载

软件介绍 草图大师&#xff08;Sketchup&#xff09;是由谷歌公司推出的一款环保型3D建模软件。草图大师可以快速和方便地创建、观察和修改三维创意&#xff0c;具有沿路径放样、导入的2D物体可随视角转动、布尔运算等功能。传统铅笔草图的优雅自如&#xff0c;现代数字科技的…

野火直播 5.7.5x | 频道丰富,有国外频道,部分支持回看

野火直播是一款专为电视盒子设计的电视直播软件&#xff0c;提供海量的电视直播资源和丰富的内容选择。涵盖全球多地的电视台直播源&#xff0c;包括央视、卫视、地方台、海外台等上千个电视频道。软件界面简洁&#xff0c;操作便捷&#xff0c;支持高清流畅播放&#xff0c;并…

题解 洛谷 Luogu P1182 数列分段 Section II 二分答案 C/C++

题目传送门&#xff1a; P1182 数列分段 Section II - 洛谷 | 计算机科学教育新生态https://www.luogu.com.cn/problem/P1182思路&#xff1a; 二分答案&#xff0c;每次以区间 [l, r] 中点 m 为每段和的阈值 判断在此前提下&#xff0c;划分段数是否不大于 M 是就记录答案…

Rust语言俄罗斯方块(漂亮的界面案例+详细的代码解说+完美运行)

tetris-demo A Tetris example written in Rust using Piston in under 500 lines of code 项目地址: https://gitcode.com/gh_mirrors/te/tetris-demo 项目介绍 "Tetris Example in Rust, v2" 是一个用Rust语言编写的俄罗斯方块游戏示例。这个项目不仅是一个简单…

Hot100 - 除自身以外数组的乘积

Hot100 - 除自身以外数组的乘积 最佳思路&#xff1a; 此问题的关键在于通过两次遍历&#xff0c;分别计算从左侧和右侧开始的累积乘积&#xff0c;以此避免使用额外的除法操作。 时间复杂度&#xff1a; 该算法的时间复杂度为 O(n)&#xff0c;因为我们只需要遍历数组两次。…

通过抓包,使用frida定位加密位置

首先我们抓取一下我们要测试的app的某一个目标api&#xff0c;通过抓api的包&#xff0c;得到关键字。 例如&#xff1a;关键字&#xff1a;x-sap-ri 我们得到想要的关键字后&#xff0c;通过拦截 类&#xff0c;寻找我们的关键字&#xff0c;及找到发包收包的位置&#xff0c…

【模型学习之路】TopK池化,全局池化

来学学图卷积中的池化操作 目录 DataBatch Dense Batching Dynamic Batching DataBatch 存取操作 TopKPooling GAP/GMP 一个例子 后话 DataBatch 当进行图级别的任务时&#xff0c;首先的任务是把多个图合成一个batch。 在Transformer中&#xff0c;一个句子的维度是…

<项目代码>YOLOv8 停车场空位识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

如何在Python中进行数学建模?

数学建模是数据科学中使用的强大工具&#xff0c;通过数学方程和算法来表示真实世界的系统和现象。Python拥有丰富的库生态系统&#xff0c;为开发和实现数学模型提供了一个很好的平台。本文将指导您完成Python中的数学建模过程&#xff0c;重点关注数据科学中的应用。 数学建…

ThingsBoard规则链节点:GCP Pub/Sub 节点详解

目录 引言 1. GCP Pub/Sub 节点简介 2. 节点配置 2.1 基本配置示例 3. 使用场景 3.1 数据传输 3.2 数据分析 3.3 事件通知 3.4 任务调度 4. 实际项目中的应用 4.1 项目背景 4.2 项目需求 4.3 实现步骤 5. 总结 引言 ThingsBoard 是一个开源的物联网平台&#xff…

【工具变量】城市供应链创新试点数据(2007-2023年)

一、测算方式&#xff1a;参考C刊《经济管理》沈坤荣和乔刚老师&#xff08;2024&#xff09;的做法&#xff0c;使用“供应链创新与应用试点”的政策虚拟变量&#xff08;TreatPost&#xff09;表征。若样本城市为试点城市&#xff0c;则赋值为 1&#xff0c;否则为 0&#xf…