使用声明隐藏名称

2024-01-17

#include <iostream>

struct H
{
    void swap(H &rhs); 
};    

void swap(H &, H &)
{
    std::cout << "swap(H &t1, H &t2)" << std::endl;
}

void H::swap(H &rhs)
{
    using std::swap;
    swap(*this, rhs);
}


int main(void)
{
    H a;
    H b;

    a.swap(b);
}

这是结果:

swap(H &t1, H &t2)

在上面的代码中,我尝试定义一个交换函数H。在函数中void H::swap(H &rhs),我使用 using 声明使名称 std::swap 可见。如果没有 using 声明,则无法编译代码,因为类中没有可用的带有两个参数的交换函数H.

我在这里有一个问题。在我看来,在我使用 using 声明之后——using std::swap,它只是使 std::swap —— STL 中的模板函数可见。所以我认为应该在STL中调​​用交换H::swap()。但结果表明,void swap(H &t1, H &t2)而是被调用。

所以这是我的问题:

  1. 为什么我不能在没有using声明的情况下调用swap?(我猜是因为类中没有带两个参数的swap函数。但我不确定。)
  2. 为什么会调用我的定义的交换而不是STL中的交换H::swap?

  1. 为什么我不能在没有 using 声明的情况下调用 swap?

我们从最近的封闭范围开始,向外移动,直到找到一些东西。有了这个:

void H::swap(H &rhs)
{
    swap(*this, rhs);
}

不合格swap finds H::swap()。然后我们进行依赖于参数的查找。但规则是,从[基本.lookup.argdep] http://eel.is/c++draft/basic.lookup#basic.lookup.argdep-3:

Let X是由不合格查找(3.4.1)产生的查找集,并令Y是产生的查找集 参数相关查找(定义如下)。如果X包含
— 集体成员的声明,或
— 块作用域函数声明不是使用声明, or
— 既不是函数也不是函数模板的声明
then Y是空的。否则Y是在与参数类型关联的命名空间中找到的声明集,如下所述。 [...]

由于非限定查找集找到类成员,因此参数相关查找集为空(即,它没有找到swap(H&, H&)).

  1. 为什么会调用我的定义的交换而不是STL中的交换H::swap?

当您添加:

void H::swap(H &rhs)
{
    using std::swap;
    swap(*this, rhs);
}

现在不合格swap finds std::swap() and not H::swap(),因为前者是在更内部的范围内声明的。using std::swap;不符合上述规则中的任何条件,这将导致Y为空(它不是类成员,它is a 使用声明,它是一个函数模板)。因此,参数相关的查找集确实包含在关联的命名空间中找到的声明 - 其中包括swap(H&, H&) (since H位于全局命名空间中)。我们最终得到了两个重载候选者 - 你的是首选,因为它是非模板。


See 谢奥的回答 https://stackoverflow.com/a/6380882/2069064关于将交换添加到您的班级的首选方式。基本上,你想写:

struct H {
    friend void swap(H&, H&) { ... }
};

这将由 ADL 找到(并且只能由 ADL 找到)。然后每当有人calls交换正确:

using std::swap;
swap(a, b);

查找会在适当的地方找到您的。

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

使用声明隐藏名称 的相关文章

随机推荐

  • 覆盖烧瓶蓝图中的路线

    有一个蓝图 定义了很多有用的路线 但我无法控制它 无法以任何方式更改它的代码 尝试在不同的应用程序中重用它 但蓝图的端点之一必须重载 我怎样才能做到这一点 我尝试在现有路线的基础上添加一条新的蓝图路线 blueprint route my
  • 行背景颜色 GtkTreeView 小部件

    我正在尝试将 gtk 树视图小部件中禁用的行着色为浅灰色 根据我所读到的内容 我应该设置相应 cellrenderer 的 background gdk 属性并将其绑定到模型列 这种作品 Gtk CellRendererText textR
  • 程序化 Jetty 关闭

    如何以编程方式关闭嵌入式jetty服务器 我像这样启动码头服务器 Server server new Server 8090 server start server join 现在 我想根据请求关闭它 例如http 127 0 0 1 80
  • 获取远程文件的最后修改日期

    我想通过curl 获取远程文件的最后修改日期 有谁知道这是怎么做到的吗 你可能可以使用这样做curl getinfo http php net manual en function curl getinfo php
  • Delphi:如何聚合 TClientDataset 中的范围记录?

    我需要使用一些聚合TClient数据集 在 SQL 中 这些聚合可以使用如下脚本完成 Select Sum column1 from table1 where Date Column lt Date Value 因为我在很长的过程和非常慢的
  • Symfony 2 Assetic 致命错误:在资产转储上找不到类“Assetic\Util\PathUtils”

    我将 Symfony 版本 2 1 10 与 Assetic 一起使用 在上次作曲家更新后 当我尝试运行时出现以下错误php app console assetic dump Dumping all dev assets Debug mod
  • 如何增加 vim 中行号边距的间距?

    我的 vim 配色方案有问题 source tinygrab com http new tinygrab com ca56d2c7a8e13f7077012bece6abd90e png 行号与代码太接近 如何增加行号右边距的宽度 这也困扰
  • 如何在 Eloquent ORM laravel 中获取最后一个插入 id

    我正在使用 Eloquent ORM in Laravel 执行数据库操作 我只想获取数据库中最后一次插入的id 不是最大id 我搜索了 laravel Eloquent ORM 中的最后一个插入 id 我得到了以下链接 Laravel 使
  • DataTables 渲染自定义列

    是否可以在 DataTables net 中呈现自定义列 我已经阅读了很多教程和文档 但无法使其正常工作 我想创建带有链接的第三列 我在其中使用第一列中的信息 我的代码如下所示 document ready function categor
  • java 正则表达式:替换 ${var}

    我正在尝试替换一个字符串 例如 Hello my name is name I am age years old with Hello my name is Johannes I am 22 years old 变量存储在 HashMap
  • canvas.toDataURL() 导致安全错误

    我正在使用 HTML5 画布和 toDataURL 功能通过动力学JS http www html5canvastutorials com kineticjs html5 canvas stage data url with kinetic
  • Spring 缓存 - 忽略键的参数

    我想缓存一个具有可选参数 下面示例中的用户代理 的简单 getter 的结果 如何在不考虑可选用户代理参数的情况下指示创建密钥 Cacheable value bookCache public Book getBooks RequestHe
  • 了解可见性:根据 W3C 文档折叠表列

    来自 W3C 的动态行列效果 https www w3 org TR CSS22 tables html dynamic effects 此折叠值会导致整个行或列从显示中删除 并且通常由行或列占用的空间可用于其他内容 从上面我的理解是 如果
  • 如何使用 Indigo 设置 Eclipse PDE/Build?

    在我的项目中 我使用 PDE Build 在 Hudson 的远程服务器上构建我的 RCP 应用程序 当前版本是基于 Eclipse Galileo 的包 它作为构建器应用程序和目标平台都可以正常工作 现在我想将其升级到 Indigo 我需
  • 无法在 Microsoft Powershell 中使用“mvn -D”参数运行 Maven,但可以在命令提示符下运行

    我正在尝试从命令行构建我们的网络项目 但跳过测试 我正在使用命令mvn clean install Dmaven test skip true 当我从传统的黑白命令提示符 又名 DOS shell 运行命令时 该命令有效 但是当我从 Win
  • 直接映射缓存

    直接映射缓存由 16 个块组成 主存包含 16K 块 每个块 8 字节 主存地址格式是什么 意思是每个字段的大小 我知道这些字段是 Tag Block Offset 我只是不知道如何获得每个的尺寸 这是作业吗 为了解决这个问题 您需要知道相
  • Android listview with Glide - 加载后位图加倍

    我正在开发一个安卓应用程序 我的片段之一包含一个简单的列表视图 显示朋友列表 每个朋友都可以有自己的个人资料图片 它是由 Glide 库设置的 当用户没有设置个人资料图片时 将显示默认图像 我的问题是 每次列表中的第一个元素都会获得与列表的
  • 如何使用 QEMU 的简单跟踪后端?

    这是后续this https stackoverflow com questions 37522552 qemu simple backend tracing dosent print anything comment65639854 37
  • javascript:禁用文本选择

    我正在使用 javascript 禁用网站上的文本选择 代码是 可以找到类似的脚本here http rainbow arch scriptmania
  • 使用声明隐藏名称

    include