为什么(不相关的)using 声明可以通过参数依赖查找来协调重载歧义?

2024-01-17

这是问题的后续here https://stackoverflow.com/questions/46782156/does-argument-dependent-lookup-go-before-normal-scope-lookup使用参数相关查找 (ADL) 进行函数重载。我想检查我对这些情况下规则的理解,所以我编写了一些测试代码。

首先,当然,std 中的 HasPtr 类没有交换,因此我编写了自己的命名空间,其中除了已在全局范围中定义的交换之外,还包含 HasPtr 版本的交换。 using 声明按照我的预期工作——产生了歧义错误,因为已经定义了一个 HasPtr 版本的 swap,如“C++ Primer”第 5 章中所做的那样。

然后我想看看如果我将 using 声明更改为 using 指令会发生什么。书上说编译器将保持沉默,直到函数被实际调用。我想验证一下,所以代码如下:

#include <string>

class HasPtr {
public:
    friend void swap(HasPtr&, HasPtr&);
    std::string *ps;
};

void swap(HasPtr &lhs, HasPtr &rhs) {
    swap(lhs.ps, rhs.ps); // swap the pointers, not the string data
}

namespace myNS {
    void swap(HasPtr &lhs, HasPtr &rhs)     {
        std::string s = "in my name space";
        swap(lhs.ps, rhs.ps); // swap the pointers, not the string data
    }
}

class Foo {
    friend void swap(Foo &lhs, Foo &rhs);
    HasPtr h;
};


void swap(Foo &lhs, Foo &rhs) {
    using std::swap;  //<- commenting this line will cause error
    using namespace myNS;
    swap(lhs.h, rhs.h);
}

int main() {
    Foo f1, f2;
    swap(f1, f2);
}

第 27 行发生了奇怪的事情(using std::swap;)。如果我将其注释掉,则名称 myNS::swap 与已在全局范围中定义的签名完全相同的签名将被提升到全局范围,从而导致重载歧义错误,正如我所预期的那样。

但是,如果我不注释第 27 行并编译,则不会报告歧义错误。并且程序执行最初在全局范围内定义的 ::swap ,就像 using 指令一样using namespace myNS;不会提升 myNS::swap,因此不会将其添加到重载的候选集中。我就是无法理解这种现象。为什么来自不相关命名空间(std 当然不包含 HasPtr 版本的 swap)的 using 声明可以协调 ADL 下的重载歧义?为什么选择执行原始的 ::swap,而不是 myNS 中的竞争对手?第 27 行对重载过程是否有任何副作用(例如,抑制提升的命名空间中的名称,以便原始名称具有更高的优先级)?谢谢您的回答。

该问题可以在 Windows 7 上的 Visual Studio 2015 Update 3 和 ubuntu 14.04 上的 GCC 4.8.4(均为 64 位)中重现。


这里起作用的机制有三个方面。

  1. A using 宣言, like using std::swap, 是一个声明。它引入了一个声明swap进入函数的声明区域。

  2. A using 指示另一方面,不会将声明引入当前声明区域。它只允许非限定查找来处理指定名称空间中的名称,好像它们是在当前声明区域的最近的封闭命名空间中声明的。

  3. 较小声明区域中的声明隐藏了较大封闭声明区域中的声明。

对于上述内容,您的设置方式如下:

  1. std::swap被声明在里面swap(Foo, Foo).
  2. 里面的名字myNS可供swap(Foo, Foo),就好像它们是在同一名称空间中声明的一样。
  3. #1 中添加的声明隐藏了所做的声明visible in #2.
  4. ::swap可以通过 ADL 找到(尽管也被 #1 隐藏),但是myNS::swap不能。自从myNS版本都是隐藏的,ADL 找不到,它不与任何内容冲突。

当您删除声明时std::swap,现在你有myNS::swap可见的。 ADL 发现::swap同时,给你两个重载。它们都是有效的重载,并产生明显的歧义。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么(不相关的)using 声明可以通过参数依赖查找来协调重载歧义? 的相关文章

  • C++ 标准是否允许未初始化的 bool 导致程序崩溃?

    我知道一个 未定义的行为 C 几乎可以让编译器做任何它想做的事情 然而 我遇到了一次令我惊讶的崩溃 因为我认为代码足够安全 在这种情况下 真正的问题仅发生在使用特定编译器的特定平台上 并且仅在启用优化的情况下发生 我尝试了几种方法来重现问题
  • Web 应用程序框架:C++ 与 Python

    作为一名程序员 我熟悉 Python 和 C 我正在考虑编写自己的简单 Web 应用程序 并且想知道哪种语言更适合服务器端 Web 开发 我正在寻找一些东西 它必须是直观的 我认识到 Wt 存在并且它遵循 Qt 的模型 我讨厌 Qt 的一件
  • 以概率从列表中选择随机元素

    我有一个包含四个项目 A B C D 的列表 每个项目都有被选择的概率 例如 A 有 74 的机会被选中 B 15 C 7 D 4 我想创建一个函数 根据其概率随机选择一个项目 有什么帮助吗 为您的项目定义一个类 如下所示 class It
  • stl 集的 C# 等效项是什么?

    我想使用 C 将一些值存储在平衡二叉搜索树中 我查看了泛型命名空间中的集合 但没有找到与 stl 集合等效的集合 我可以使用什么通用集合 我不想存储键 值对 只是值 你可以使用HashSet http msdn microsoft com
  • 如何通过C#在SQLite数据库中写入变量DateTime值?

    我很新C and SQLite数据库并有一些变量存储在 SQLite 数据库中TimeStamp 这是我的代码 DateTime now DateTime Now m dbConnection new SQLiteConnection Da
  • 更新 OSX 命令行工具 6.3 后缺少 C++ 标头 <__debug>

    从 App Store 更新到 Command Line Tools 6 3 后 程序包括
  • C++ 为非虚方法指定初始化

    我有 a h 如下所示 class A public void doSomething 0 然后我有 b h 如下所示 include a h class b public A public void doSomething 我只是想通过尝
  • 模板“内联”函数的静态局部变量[重复]

    这个问题在这里已经有答案了 static的局部变量inline如果我的理解是正确的 C 中的函数保证像单个全局变量一样存在 如果inline函数是一个模板 编译器可以在哪里生成该函数的多个版本 下面这篇文章应该很好地回答你的问题 http
  • 尝试缓冲区溢出

    我正在尝试使用缓冲区溢出来更改函数的结果 以使用以下代码更改堆栈上的结果 include
  • 谷歌基准迭代的意义是什么?

    我正在使用 Google Benchmark 来测量某些代码的执行时间 例如 我编写了以下代码来测量其执行时间性能 include
  • 具有多重继承的不明确基数

    我正在尝试在一个大库中编写一些类的子类 我收到 基础不明确 错误 这是该问题的一个可编译示例 include
  • 阻止用户取消选择列表框中的项目?

    我有一个列表框 里面有很多项目 用户可以单击某个项目来编辑其内容 如何防止用户取消选择所有项目 即 用户不应该无法选择任何内容 您的情况缺少一个案例 即清除列表后 您将选择列表中不再存在的项目 我通过添加额外的检查来解决这个问题 var l
  • C++头文件问题

    我在处理类时尝试了一些 C 代码 这个问题出现在我身上 并且让我有点烦恼 我创建了一个包含类定义的头文件和一个包含实现的 cpp 文件 如果我在不同的 cpp 文件中使用此类 为什么要包含头文件而不是包含类实现的 cpp 文件 如果我包含类
  • 向窗口句柄发送消息

    我尝试使用 sendmessage 将消息从我的 C 应用程序传递到 C 我的c 代码是这样的 int tmain int argc TCHAR argv COPYDATASTRUCT cpd cpd dwData 0 LPCWSTR st
  • Roslyn,通过 hostObject 传递值

    我正在尝试通过 hostObject 发送一个类 但显然它不想工作 using Roslyn Compilers using Roslyn Compilers CSharp using Roslyn Scripting using Rosl
  • 将 .NET 类库(主要定义 CRUD 操作)公开为服务

    公开现有内容的最佳 有效和最快的方法是什么 类 图书馆 主要定义 CRUD 操作 作为service 周转基金服务 or WCF数据服务 以便它可以与银光 or Ajax 在那儿tools 代码生成器 RAD 工具 哪些可以支持这个 预先感
  • 如何将这个基于代码的 WPF 工具提示转换为 Silverlight?

    以下工具提示代码适用于WPF 我正在努力让它发挥作用银光 但它给了我这些errors TextBlock does not contain a definition for ToolTip Cursors does not contain
  • 在运行时将项目添加到 ToolStrip

    您好 我有一个带有 收藏夹 菜单的 ToolStripMenu 我想在运行时在 WinForms 应用程序中添加子项目 我有一个 datagridview 右键单击它会显示一个包含 添加到收藏夹 选项的上下文菜单 当该事件被触发时 我想使用
  • “while(true) { Thread.Sleep }”的原因是什么?

    我有时会遇到以下形式的代码 while true do something Thread Sleep 1000 我想知道这是否被认为是好的做法还是坏的做法以及是否有任何替代方案 通常我在服务的主函数中 找到 这样的代码 我最近在 Windo
  • InvalidOperationException:没有为方案“CookieSettings”注册身份验证处理程序

    我正在使用 ASP Net MVC core 2 1 开发一个应用程序 其中不断出现以下异常 InvalidOperationException 没有为方案 CookieSettings 注册身份验证处理程序 注册的方案有 Identity

随机推荐

  • 使用 lkJSON 解析 JSON

    我有一个 JSON 文件 需要解析并提取一个值 user pk 25025320 username instagram full name Instagram is private false profile pic url https i
  • 实现时在 typescript 中找不到 OnInit

    我正在使用 loginComponent 开发一个示例项目 当我尝试添加 OnInit 时 我需要在我的类中实现 OnInit 但出现以下错误 ts 找不到 OnInit 这是我的代码 export class loginComponent
  • JSON.Stringify 将引号添加到 ID [重复]

    这个问题已经存在了 我正在使用 JSON stringify 和 JSON parse 根据对在线数据库的更改来编辑我的 JSON 文件 一切正常 除了在数字周围加上引号 这会搞乱 JSON 文件 例如应该是 id 1但它正在打印出来 id
  • java SwingWorker.doInBackground() 不得访问 GUI 元素

    也许这很微不足道 我正在努力理解一个简单的文档摇摆工人 http docs oracle com javase 6 docs api javax swing SwingWorker html 这是复制粘贴的内容 Workflow Swing
  • 在 IValueConverter 类中定义属性

    我需要在转换器类中定义 DependencyProperty 因为我需要此数据来进行转换 并且此数据位于另一个对象中 而不是我绑定到的对象中 我的转换器类如下 public class LEGOMaterialConverter Depen
  • 如何在tomcat访问日志中记录Client IP和X-Forwarded-For IP

    如何在 tomcat 访问日志中记录 Client IP 和 X Forwarded For IP 我正在使用 X Forwarded For i 如果我通过负载均衡器访问 它会记录实际的客户端地址 但如果我直接访问 tomcat 实例 则
  • 从 glmmTMB 类的 ZINB 模型生成预测计数分布

    在上一个问题中 R 中没有从 Zeroinfl 对象预测零 https stackoverflow com questions 22314921 no zeros predicted from zeroinfl object in r 有一
  • 这个“>>=”运算符在 C 中意味着什么?

    unsigned long set set is after modified set gt gt 1 我在内核系统调用中发现了这个 但我不明白 它是如何工作的 表达方式set gt gt 1 means set set gt gt 1 即
  • using 语句 - 它会触发垃圾收集吗?

    我想做的是包装一些可能在 using 语句中泄漏的可疑函数来触发垃圾收集 有人使用或见过这样的东西吗 这有效吗 您对此有何看法 using String wrapper new String maybe this will trigger
  • AGP 7.0.0-alpha15之后如何更改版本代码

    在 AGP 7 0 0 alpha15 之前 我可以更改应用程序的版本代码 例如这样 android defaultConfig applicationVariants all if buildType name debug outputs
  • Three.js 加载已三角化的网格是否比使用四边形的网格性能更高?

    我读过 Three js 对所有网格面进行三角剖分 这是正确的吗 然后我意识到我使用的大多数 gltf 模型都有四面体 在 Blender 中对面进行三角测量非常容易 所以我很好奇对面进行预先三角测量是否会导致网格加载更快 提前致谢 如果您
  • 如何使用 R 运行 ldap 查询?

    我想对 LDAP 目录进行查询 了解员工在部门和组中的分布情况 就像是 给我一个小组所有成员的部门名称 然后使用 R 进行频率分析 但我找不到任何有关如何使用 R 连接和运行 LDAP 查询的示例 RCurl 似乎有某种支持 http cr
  • JSF:将 A.jsf 设置为键入 mydomain.com 时要转到的默认页面

    现在 每次我打字mydomain com它会自动转到mydomain com projectname home jsf 这是我的登录页面 不知道为什么 我知道我仍在会话中 这意味着我可以导航到受限页面而无需再次登录 那么如果我输入的话我该怎
  • 尝试上传到 s3 时出现 InvalidAccessKeyId

    我正在使用aws sdk将文件上传到 s3 我正在配置我的凭据 aws config update accessKeyId aws config credentials accessKeyId secretAccessKey aws con
  • 如何在 C 中定义和使用位数组?

    我想创建一个非常大的数组 在上面写入 0 和 1 我正在尝试模拟一种称为随机顺序吸附的物理过程 其中长度为 2 的二聚体单位沉积在 n 维晶格的随机位置上 且彼此不重叠 当晶格上没有足够的空间来沉积更多二聚体时 晶格被堵塞 该过程就会停止
  • Rake 任务之间如何通信?

    假设我有一个目标需要编译一些文件 该目标有另一个目标作为先决条件 即获取文件的目标 这么说吧 task obtain do obtain files from somewhere end task compile gt obtain do
  • Java:当被另一个线程中断时,如何捕获线程上的 InterruptedException?

    我正在开发一个多线程应用程序来建立与外部服务器的连接 每个服务器都在单独的线程上 并且将被阻止 直到有输入 其中每一个都扩展了 Thread 类 为了便于解释 我们将这些称为 连接线程 所有这些连接线程都存储在并发哈希图中 然后 我允许 R
  • 原则 2 子查询

    我想使用查询生成器实现子查询 但我不理解语法 我正在处理一个位置表 其中的条目可以是城市 州或邮政编码 具体取决于设置的位置类型 我想获取某个州的所有位置 并删除任何城市类型且人口低于一定数量的位置 qb gt select l gt fr
  • lush() java 文件处理

    lush 的具体用途是什么 流和缓冲区有什么区别 为什么我们需要缓冲区 缓冲的优点是效率 通常 将 4096 字节的块写入文件一次比写入 4096 次一个字节要快 缓冲的缺点是您会错过反馈 句柄的输出可以保留在内存中 直到写入足够的字节以使
  • 为什么(不相关的)using 声明可以通过参数依赖查找来协调重载歧义?

    这是问题的后续here https stackoverflow com questions 46782156 does argument dependent lookup go before normal scope lookup使用参数相