模板化运算符重载决策,成员函数与非成员函数

2023-12-20

当尝试 clang-3.4(从 gi​​t 编译)时,它无法编译我的一个项目,抱怨在解决重载运算符时存在歧义。 我发现有两个模板化运算符,其中一个被声明为成员函数,另一个被声明为非成员函数,两者看起来同样匹配。

下面SSCCE演示了这种情况:

#include <iostream>

struct ostr {
        std::ostream& s;

        template<class T>
        ostr& operator<<(const T& x) { s << x; return *this; }
};

struct xy {
        double x, y;
};

template<class Stream>
Stream& operator<<(Stream& s, const xy& x) {
        s << "[" << x.x << ", " << x.y << "]";
        return s;
}

int main() {
        ostr os{std::cout};
        xy x{4, 5};
        os << "Value is: " << x <<"\n";
}

该项目之前编译得很好,我用几个编译器再次检查了这个 SSCCE (gcc 4.5, 4.6, 4.7, 4.8 and clang 3.3)并且他们所有人都在没有任何警告的情况下编译了它(带有-Wall -Wextra -pedantic)。所有编译器均设置为 C++11/C++0x 标准。 添加 ctor 之后ostr,即使在MSVC 2012 and 2010)

两者兼得operator<<s 非成员在所有编译器中都表现出歧义(如预期)

浏览标准草案后(N3242 and N3690)我没有找到任何使成员函数/运算符比非成员函数/运算符更好匹配的内容。

所以我没能证明clang-3.4是错的,我想知道谁是对的。 因此我的问题是:

  • 该代码有效吗?成员运算符/函数是否应该比非成员运算符/函数更好匹配,这是 clang-3.4 中的一个错误?
  • 或者所有其他编译器都错误/过于宽容?

我知道改变第二个operator<<到非模板化函数(带有std::ostream而不是模板参数)将解决歧义并按预期工作,但这不是这里的重点。


重载决议向成员函数添加一个附加参数只是为了重载决议的目的:

[over.match.funcs]/2

候选函数集可以包含要根据同一参数列表解析的成员函数和非成员函数。为了使自变量和参数列表在这个异构集合中具有可比性,成员函数被认为有一个额外的参数,称为隐式对象参数,它表示已调用成员函数的对象。

/4

对于非静态成员函数,隐式对象参数的类型为

—“左值引用cv X” 对于没有声明的函数引用限定符或与& 引用限定符

—“右值引用cv X” 对于用&& 引用限定符

where X是该函数所属的类,并且cv is the cv- 成员函数声明的限定。

遵循一些特殊规则,例如允许将右值绑定到此隐式对象参数(用于调用右值上没有引用限定符的成员函数,例如ostr{std::cout}<<"hello").


函数签名包括我们需要比较重载解析的隐式对象参数是:

template<class T>
ostr& ostr::operator<<(ostr&, const T&);    // F1

template<class Stream>
Stream& ::operator<<(Stream&, const xy&);    // F2

替换后os << x,我们得到same签名:

ostr& ostr::operator<<(ostr&, const xy&);
ostr& ::    operator<<(ostr&, const xy&);

因此,只有 [over.match.best]/1 中的“决胜局”之一可以解决歧义。事实上,可以应用,即“F1比更专业F2"(反之亦然):函数模板的部分排序。

注意:指定添加隐式对象参数的过程again在部分排序的描述中[temp.func.order]/3。


对于部分订购F1 and F2(如上所述),我们首先创建两个独特的类型:

struct unique_T {};
struct unique_Stream {};

然后我们改造F1 into F1'通过替换模板参数T具有独特的类型unique_T(同样对于F2):

ostr& ostr::operator<<(ostr&, const unique_T&);
ostr& ::    operator<<(unique_Stream&, const xy&);

变换函数的参数F1'现在用于尝试推导未转换的模板参数F2:

ostr a0;
unique_T a1; // no reference, no cv-qualifier
::operator<<(a0, a1) // does template argument deduction succeed?

// reminder: signature of ::operator<<
template<class Stream>
Stream& ::operator<<(Stream&, const xy&);

扣除成功为a0 [with Stream = ostr],因此类型ostr& from F1被认为至少与相应的第一个参数的类型一样专业F2 (Stream&, with Stream是模板参数)。我不确定第二个参数会发生什么a1,因为第二个参数没有发生扣除::operator<<(它的类型是const xy&).

现在我们用参数重复这个过程F2'并尝试推导模板参数F1:

unique_Stream a0;
xy a1;
ostr::operator<<(a0, a1);

// reminder: signature of ostr::operator<<
template<class T>
ostr& ostr::operator<<(ostr&, const T&);

在这里,第一个参数没有发生演绎,但第二个参数发生并成功 [withT = xy].

我的结论是,没有哪个函数模板比​​它更专业了。因此重载解析应该失败由于含糊不清。

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

模板化运算符重载决策,成员函数与非成员函数 的相关文章

  • 使用 QTextCursor 选择一段文本

    使用 Qt 框架选择文本片段时遇到问题 例如 如果我有这个文件 没有时间休息 我想选择 ime for r 并从文档中删除这段文本 我应该如何使用 QTextCursor 来做到这一点 这是我的代码 QTextCursor cursor n
  • 无法在更新面板中找到上传的文件

    aspx
  • ObservableCollection 上的“Cascade”绑定,包含其他 ObservableCollection

    我有一个项目需要显示合同列表 Class Affaire 每个合约都有一个阶段列表 类别阶段 我使用绑定在 2 个不同的 ListView 中显示它们中的每一个 问题是当我从 ListView 中删除一个 Phase 时 显示 Phases
  • 在 C 中声明和初始化数组

    C 有没有办法先声明然后初始化数组 到目前为止 我一直在初始化一个这样的数组 int myArray SIZE 1 2 3 4 但我需要做这样的事情 int myArray SIZE myArray 1 2 3 4 在 C99 中 您可以使
  • 设置外部应用程序焦点

    在 VB NET 中 您可以使用以下命令将焦点设置到外部应用程序 AppActivate Windows Name or AppActivate processID As Integer 现在 如果您这样做 则效果很好 Dim intNot
  • ResourceDictionary 源中的 Uri 语法(通用 Windows 平台)

    我正在迁移我的Windows 8 1项目到Windows 10 通用 Windows 平台 这时我被拦住了ResourceDictionary改变在UWP 为了简单起见 我有包含 2 个项目的 Windows 8 1 解决方案 App pr
  • 按位非运算符

    为什么要按位运算 0 打印 1 在二进制中 不是0应该是1 为什么 你实际上很接近 在二进制中 不是0应该是1 是的 当我们谈论一位时 这是绝对正确的 然而 一个int其值为0的实际上是32位全零 将所有 32 个 0 反转为 32 个 1
  • 使用 MapViewOfFile 有什么限制吗?

    我正在尝试将内存映射文件用作 hFile CreateFile State Path GENERIC READ FILE SHARE READ FILE SHARE WRITE 0 OPEN EXISTING FILE FLAG SEQUE
  • 在 Asp.Net 模板中转义内联代码块

    我有一个页面 我希望在其中呈现以下 html 一个小的 JS 模板 然而 Asp NET 预处理器正在拾取 我已经设法通过文字控件来做到这一点 并在后面的代码中设置它的文本 我理想地希望将其保留在 aspx 页面中 这是我能找到的最好的解决
  • 在标准库中静态链接时如何支持动态插件?

    假设一个应用程序myapp exe是使用构建的g 它使用标志 static libstdc 这样就可以安装在没有环境的情况下libstdc so myapp exe还添加了对某些功能的插件支持plugf可以通过动态加载dlopen来自共享库
  • 使用 for 循环创建链表

    这是我的结构 struct ListItem int data struct ListItem next 假设链表的第一个节点的 data 0 我想编写一个 for 循环来创建大小为 5 的链表 但我不知道如何工作 我尝试了以下方法 int
  • 带有 Unicode 字符的主机名在 Windows 8 中有效

    Uri CheckHostName 回报UriHostNameType Unknown到处都是 但在 Windows 8 上 它又回来了UriHostNameType Dns 为什么突然间带有 Unicode 西里尔字符的主机名在 Wind
  • C# Linq 可以做组合数学吗?

    我有这个数据结构 class Product public string Name get set public int Count get set var list new List
  • 一些涉及类析构函数和删除运算符的内存管理问题?

    在阅读了一些教程后 我仍然不清楚 C 中内存管理的一些观点 1 当使用 new 运算符声明的类超出范围时 是否会调用其析构函数并释放内存 是否有必要调用删除运算符来释放类的内存并调用其析构函数 class Test void newTest
  • C语言中如何将整数转换为字符? [复制]

    这个问题在这里已经有答案了 C语言中如何将整数转换为字符 C 中的字符已经是数字 字符的 ASCII 代码 无需转换 如果要将数字转换为相应的字符 只需添加 0 即可 c i 0 0 是 ASCii 表中的一个字符
  • 如何最好地为 Visual Studio 2017 构建的 CMake C++ 项目设置输出目录?

    我使用 Visual Studio 2017 使用 vcxproj 文件构建 C 桌面项目 我喜欢默认行为 其中输出目录是项目下面的子目录 例如 myproj sln myproj vcxproj x64 myproj release my
  • 在发送传出请求之前将新的 SoapClient 绑定到特定 IP 地址

    假设应用程序所在的计算机具有 SoapClient 具体来说 我正在使用 Microsoft Web Service3 Messaging SoapClient 它通过发送传出请求并获取 SoapEnvelope 作为回报 完善的流程 与远
  • 序列化时如何跳过 xml 声明?

    我正在尝试输出一个没有 xml 头的 xml 文件 例如 我试过 Type t obj GetType XmlSerializer xs new XmlSerializer t XmlWriter xw XmlWriter Create c
  • C# 记录类型:记录子类之间的相等比较

    给定父记录类型 public record Foo string Value 和两个记录子类Bar and Bee我想知道是否可以实施Equals在基类中 因此 Foo Bar 或 Bee 的实例都被考虑equal基于Value 两者都与E
  • 在 C++ 中将大型数据向量写入/读取到二进制文件

    我有一个 C 程序 它通过将 ascii 文件中的网格人口数据读取到大型 8640x3432 元素双精度向量中来计算给定半径内的人口 将 ascii 数据读入向量大约需要 30 秒 循环每列和每行 而程序的其余部分只需要几秒钟 我被要求通过

随机推荐

  • 如何使用动态行跨度显示数据库中的数据

    我是 php 编程新手 在使用 php 和 html 显示 mysql 数据库中的数据时遇到一些问题 这是我的桌子 location id location location component id comopnent id locati
  • C 多类型函数

    我想用 C 编写一些函数 但它们必须适用于所有数字类型 int float double 什么是好的做法 在 void 上使用指针 当然还有指向函数的指针 或者为每种类型编写不同的函数 例如 float func float a float
  • pyenv 在执行所述模块时在终端中打印模块

    我已经转向使用pyenv运行 python 时 但问题是当我执行一个模块并且该模块导入其他模块时pyenv经常会打印出一大堆对我来说是胡言乱语的内容 例如 alias py37 pyenv local 3 7 3 python Admins
  • Symfony2 __toString() 错误

    我在将实体保存回给我时遇到此错误 Catchable Fatal Error Method My BusinessBundle Entity Type toString must return a string value in var w
  • 使用rest api在Google Drive中创建新文件夹

    仅当谷歌驱动器不存在时 如何使用 python 在谷歌驱动器中创建新文件夹 我对这个 google API 和 python 完全陌生 我的帐户有一个访问令牌 我想使用它创建文件夹 创建文件夹 import json import requ
  • 当 BOM(字节顺序标记)丢失时,如何才能最好地猜测编码?

    我的程序必须读取使用各种编码的文件 它们可能是 ANSI UTF 8 或 UTF 16 大端或小端 当 BOM 字节顺序标记 存在时 我没有问题 我知道该文件是 UTF 8 还是 UTF 16 BE 或 LE 我想假设当没有 BOM 时该文
  • 英特尔 Fortran 95 编译器是否允许模块数组具有非常量大小?

    我已经下载了 Fortran 90 95 自适应网格细化库 Paramesh http www physics drexel edu olson paramesh doc Users manual amr html 现在我正在尝试编译一个附
  • 如何停止水平滚动?

    我用 html 和 javascript 编写了一个文件 垂直滚动应该存在 但我想停止水平滚动 我怎样才能做到这一点 萨弗拉兹有已经提到过 https stackoverflow com questions 2987261 how to s
  • 如何为 BN_generate_prime 播种 PRNG

    我一直无法找到关于在 openssl bn h 中使用 BN generate prime 生成素数的答案 另外 我如何播种该函数使用的 PRNG 单独的问题但与我的代码相关 我正在编写一个程序来生成 RSA 密钥对 如何检查高位是否设置为
  • Angular UI bootstrap - 在 typeahead-no-results 上显示下拉菜单

    尝试在预输入没有结果时获取下拉菜单 但是下拉菜单不显示 看法 div class dropdown div class form group div div
  • 如何在 ggplot2 / Rmarkdown 中跨选项卡进行分面?

    我知道facet wrap and facet grid用于刻面 对于需要更多空间的更详细的图形 能够轻松地进行分面可能会很有用Rmarkdown 选项卡 https stackoverflow com a 38146093 除了将图形的代
  • 为什么 O(1) != O(log(n)) ?对于 n=[整数,长整型,...]

    例如 假设 n Integer MAX VALUE 或 2 123 那么 O log n 32 和 123 就是一个小整数 不是 O 1 吗 有什么不同 我认为 原因是 O 1 是常数 但 O log n 不是 还有其他想法吗 If n上面
  • 使用 Gradle 将 .ebextensions 添加到 Spring Boot Jar 的简洁方法

    是否有一种干净的方法可以将其他根文件夹添加到使用默认 bootRepackage jar 生成的 Spring Boot Jar 文件中 就我而言 我需要 AWS beanstalk 的 ebextenions 文件夹 我知道我可以破解它
  • 尝试对值进行分组?

    我有一些这样的数据 1 2 3 4 5 9 2 6 3 7 我正在寻找这样的输出 组 ID 和该组的成员 1 1 2 6 2 3 4 7 3 5 9 第一行 因为 1 连接 到 2 而 2 连接到 6 第二行 因为 3 连接到 4 3 连接
  • Java使Proxy Socket多线程化

    我已经构建了一个 java 代理 它可以工作 但只允许 1 个客户端 我知道我需要进行多线程处理 这就是我这样做的原因 因此它会打开新线程 但由于某种原因我无法让它工作 这是我的代理类 public class Proxy private
  • 升级到 Xcode 5.0 后,Xcode 无法使用所选设备运行

    我今天升级到了xcode 5 0 然后我按下播放键在 iOS 模拟器中运行我的项目 这最初是有效的 然后我决定运行分析器 当我这样做时 我收到消息 Xcode cannot run using the selected device Cho
  • 列表理解中的函数 - 是否多次评估[重复]

    这个问题在这里已经有答案了 哪一个是在 python 中进行列表理解的更好方法 就计算时间和 CPU 周期而言 在示例 1 中 值 f r 是在每次迭代中计算还是计算一次并缓存 y x f r for x in xlist c f r y
  • AWS 无服务器功能未响应图像

    我正在尝试让 AWS API Gateway 使用图像进行响应 我的无服务器 Lambda 代码如下 const express require express const serverless require serverless htt
  • Python 3 中的 io.StringIO 与 open()

    我能找到的就是这个陈述 https docs python org 3 library io html text i o 创建文本流的最简单方法是使用 open 可选 指定编码 f open myfile txt r encoding ut
  • 模板化运算符重载决策,成员函数与非成员函数

    当尝试 clang 3 4 从 gi t 编译 时 它无法编译我的一个项目 抱怨在解决重载运算符时存在歧义 我发现有两个模板化运算符 其中一个被声明为成员函数 另一个被声明为非成员函数 两者看起来同样匹配 下面SSCCE演示了这种情况 in