gcc *有时*以一种奇怪的方式解决重载歧义

2024-03-22

在回答之前:这不是一个关于如何让这段代码做我想做的事情的问题。我已经知道该怎么做(参见这个问题的结尾)。这是一个关于理解编译器为什么要做它所做的事情的问题。

请考虑以下(简化的)代码:

#include <iostream>

void operator>>( std::istream &stream, char chr )
{
    std::cout<<"Called "<<chr<<"\n";
}

int main()
{
    char c='b';
    std::cin>>c;

    return 0;
}

使用 gcc 4.8.2 和 -Wall -Wextra 编译会产生一个不相关的警告(流未使用)。但是,运行时会打印“Called b”。

我预计会发生两件事之一。程序要么从标准输入读取一个字符,要么代码无法编译,因为编译器发现我的运算符和标准库定义的运算符不明确。标准库定义的运算符,根据我的理解,相当于:

std::istream &operator>>( std::istream &stream, char &c )

不管怎样,我都没想到会打电话给我的接线员。

更奇怪的是,由于上面提到的歧义,以下代码无法编译:

#include <iostream>

void function(char &chr)
{
    std::cout<<"1 "<<chr<<"\n";
}

void function(char chr)
{
    std::cout<<"2 "<<chr<<"\n";
}

int main()
{
    char c='a';
    function(c);

    return 0;
}

除了使用函数而不是运算符之外,我认为编译器对这两种情况的决定没有任何区别。

注意:我完全意识到标准库定义的内容与我上面写的原型并不完全相同。我认为,当涉及到解析函数时,至少在这个用例中,没有什么区别。请记住,std 定义不能有默认参数,因为这是运算符重载。

另外,正如我在问题开头所写的那样,我已经知道如何使代码做正确的事情。使用“const char &”而不是“char”定义运算符会导致编译器选择正确的重载。


对于通话std::cin>>c;有两个可行的功能。你所声明的那个

void operator>>( std::istream &stream, char chr );

以及在 Streams 库中定义的一个(作为函数模板的专门化):

template< class CharT, class Traits >
basic_istream<CharT,Traits>& operator>>( basic_istream<CharT,Traits>& st, CharT& ch );

选择最终赢得重载决议的最佳可行函数,如下所示13.3.3 [over.match.best]:

1 ICSi(F) 定义如下:

— 如果 F 是静态成员函数,则 ICS1 (F) 的定义使得 ICS1 (F) 既不比 ICS1 更好也不比 ICS1 更差 (G) 对于任何函数 G,并且对称地,ICS1 (G) 都不是更好 不比 ICS1 (F) 更差;否则,

— 让 ICSi(F) 表示 隐式转换序列,用于转换中的第 i 个参数 列出可行函数 F 的第 i 个参数的类型。 13.3.3.1 定义隐式转换序列和 13.3.3.2 定义了一个隐式转换序列是一个更好的转换序列或更差的转换序列意味着什么 其他。

考虑到这些定义,可行的函数 F1 被定义为更好的 函数比另一个可行函数 F2 如果对于所有参数 i, ICSi(F1) 并不是比 ICSi(F2) 更差的转换序列,然后

— 对于某些参数 j,ICSj(F1) 是比 ICSj(F2),或者,如果不是这样,

— 上下文是一个初始化 用户定义的转换(参见8.5、13.3.1.5和13.3.1.6)和 从 F1 的返回类型到 目标类型(即正在初始化的实体的类型)是 比标准转换序列更好的转换序列 F2 到目标类型的返回类型。
[ 例子:omitted] 或者,如果不是这样,

F1 是非模板函数 F2 是函数模板特化,或者,如果不是这样的话,

— F1 和 F2 是函数模板特化,并且函数 根据 F1 的模板比 F2 的模板更专业 14.5.6.2 中描述的部分排序规则。

2 如果恰好有一个可行的函数是更好的函数 比所有其他可行的功能,那么它是由 过载解析;否则调用的格式不正确。

为了简化它 - 在其他条件相同的情况下,非模板比模板特化更匹配。

在示例中function,候选人之间不存在这种区别。调用所需的两个隐式转换序列(char->char& and char->char) 是身份转换并且是不明确的。

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

gcc *有时*以一种奇怪的方式解决重载歧义 的相关文章

  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • 如何使用Java打开和关闭虚拟键盘

    我尝试了这里的所有答案 在Java程序中打开Windows虚拟键盘 https stackoverflow com questions 4948420 open the windows virtual keyboard in a java
  • 抽象类中受保护的抽象或公共抽象方法

    嗨 我有一个抽象类 其中有一些公共方法和一些抽象方法 我有公众 以便他们实现派生类的通用方法 让我困惑的是为什么我想要定义一个公共抽象方法而不是受保护的抽象方法 对我来说 在抽象类中定义公共抽象方法是没有意义的 因为 if 是一个抽象 在派
  • Laravel 5,连接子句中的派生表?

    我有这样的疑问 SELECT FROM blog LEFT JOIN SELECT blog id AVG value as blog rating FROM blog ratings GROUP BY blog id T ON T blo
  • 绘制的 envfit 向量与 NMDS 分数不匹配

    我制作了一个 NMDS 图并绘制了我的环境 如下所示 mytable 的数据框 sites c Site A Site B Site C Site D Site E Site F Site G Site H Site I Site J Si
  • heroku无法安装zbar

    我有一个 Django 应用程序 它使用 zbar 进行条形码识别 它在我的开发人员机器上运行良好 但当我尝试将其部署到 Heroku 时 我的提交被拒绝 并显示以下消息 Installing collected packages zbar
  • 调用 FileWriter 的单元测试方法

    我正在尝试为调用 FileWriter 的方法编写单元测试 我正在使用 JUnit 4 8 Powermock 和 Mockito 我正在测试的方法看起来像这样 public void methodToTest String fileNam
  • 在 pandas 中,按 DatetimeIndex 中的日期进行分组

    考虑以下综合示例 import pandas as pd import numpy as np np random seed 42 ix pd date range 2017 01 01 2017 01 15 freq 1H df pd D
  • Swift 3:将字符串转换为数组

    我在 SWIFT 3 上的应用程序上 我在屏幕上显示一个句子并记录用户的声音以查看是否匹配 我想提取句子中的每个单词来单独比较每个单词 我使用代码 let StringToLearn word text let StringToLearnA
  • 更改 SQL Server 中的用户定义类型

    我在数据库中创建了一些用户定义的类型 如下所示 CREATE TYPE dbo StringID FROM nvarchar 20 NOT NULL 并将它们分配到不同的表中 我的数据库中的表具有各种模式 不仅dbo 但我意识到我需要更大的
  • 使用jquery打开文件浏览器

    我有以下代码 p Select a file p
  • 使用 NavigationLink 将信息传递到另一个视图

    我有以下视图 我需要通过item内容到另一个视图 DetailsEvent swift 我正在使用NavigationLink 我使用的是 Xcode 11 GM struct Events View ObservedObject var
  • HDFS如何计算可用块?

    假设块大小为 128MB 则集群有 10GB 因此大约 80 个可用块 假设我创建了 10 个小文件 这些文件总共占用磁盘上 128MB 块文件 校验和 复制 和 10 个 HDFS 块 如果我想向HDFS添加另一个小文件 那么HDFS使用
  • 谷歌地图API可以进行语音导航吗?

    如何使用 google 地图 api v3 激活基于语音的方向 我已经实现了给出从起点到终点的方向的地图 但现在我想听听我当前所在位置的名称 请帮忙 我在 ios UIWebView 中实现了它 所以我从 GPS 获取当前位置 现在我每 2
  • JavaScript - for循环问题中变量递增

    我试图创建一个 for 循环 递增数字 1 4 并打印它们 但是当我在循环后打印 i 的值时 我的代码输出 5 for i 1 i lt 5 i document write i br Outputs numbers 1 4 documen
  • Kinect 1.8 颜色帧和深度帧不协调

    我的程序存在深度和彩色图像之间协调不佳的问题 玩家面具与人物不在同一位置 见下图 void AllFreamReady object sender AllFramesReadyEventArgs e using ColorImageFram
  • 等待 5 秒再执行下一行

    下面这个函数并没有像我想要的那样工作 作为一个 JS 新手 我不明白为什么 我需要它等待 5 秒钟 然后再检查是否newState is 1 目前 它不会等待 而是立即检查 function stateChange newState set
  • 将 zip 文件导入为库 - Eclipse Java

    我在导入 google http 库时陷入困境 我在链接中做了一些研究 例如 Eclipse Java 如何导入 zip 格式的库 https stackoverflow com questions 14375810 eclipse jav
  • 将 Java 对象转换为 Java Map

    我在用org eclipse jetty util ajax JSON解析 JSON 文本 但是JSON parse 字符串 方法生成一个对象 我需要它作为映射 在内部 它正是所提到的类的对象 但是 如何在不构造新对象或收到未经检查的转换警
  • 如何配置 Webpack 开发服务器来为特定文件夹提供服务,同时通过不同的服务器运行站点的其余部分?

    一些简单的背景知识 我公司的站点运行 CMS 并由 CMS 处理所有路由 没有 html 文件 只有 razor 文件 cshtml 虽然我更愿意从头开始重做网站 但这不是一个选择 因此我尝试通过将 vue js 与 webpack 开发工
  • gcc *有时*以一种奇怪的方式解决重载歧义

    在回答之前 这不是一个关于如何让这段代码做我想做的事情的问题 我已经知道该怎么做 参见这个问题的结尾 这是一个关于理解编译器为什么要做它所做的事情的问题 请考虑以下 简化的 代码 include