仅防止二元运算符的隐式转换运算符

2024-04-05

我遇到了一个问题,我已将其归结为以下问题,其中==即使应该失败,运算符用法也会编译(C++17,在 GCC 5.x、8.x 和 9.x 上测试):

template <int N> struct thing {
  operator const char * () const { return nullptr; }
  bool operator == (const thing<N> &) const { return false; }
};

int main () {
  thing<0> a;
  thing<1> b;
  a == b; // i don't want this to compile, but it does
}

它进行编译的原因是编译器选择这样做:

(const char *)a == (const char *)b;

而不是这个:

// bool thing<0>::operator == (const thing<0> &) const
a.operator == (b);

因为后者不匹配,因为b is a thing<1> not a thing<0>。 (顺便说一下,它还产生unused-comparison使用原始比较运算符时发出警告;没什么意思,但这就是出现这些警告的原因。)

我已经验证了这一点(实际上这就是我发现原因的方式)C++ 见解 https://cppinsights.io/,输出:

template <int N> struct thing {
  operator const char * () const { return nullptr; }
  bool operator == (const thing<N> &) const { return false; }
};

/* First instantiated from: insights.cpp:7 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
struct thing<0>
{
  using retType_2_7 = const char *;
  inline operator retType_2_7 () const
  {
    return nullptr;
  }
  
  inline bool operator==(const thing<0> &) const;
  
  // inline constexpr thing() noexcept = default;
};

#endif


/* First instantiated from: insights.cpp:8 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
struct thing<1>
{
  using retType_2_7 = const char *;
  inline operator retType_2_7 () const
  {
    return nullptr;
  }
  
  inline bool operator==(const thing<1> &) const;
  
  // inline constexpr thing() noexcept = default;
};

#endif


int main()
{
  thing<0> a = thing<0>();
  thing<1> b = thing<1>();
  static_cast<const char *>(a.operator const char *()) == static_cast<const char *>(b.operator const char *());
}    

显示最后一行中的转换运算符用法main.

我的问题是:当然,如果我显式地显示转换运算符,整个事情就会正常运行,但是我真的很想保留隐式转换运算符and让编译器强制正确使用operator ==(其中“正确”= 如果参数类型不同则无法编译)。这可能吗?

请注意,它是not对我来说很重要thing<N> == const char *工作。也就是说,我不需要这个重载:

bool thing<N>::operator == (const char *) const

所以我不在乎解决方案是否会破坏这种味道==.

我确实在这里搜索了其他帖子;有一些具有误导性的相似标题,但最终却毫无关联。看起来像这个帖子 https://stackoverflow.com/questions/36392600/binary-operator-overloading-implicit-type-conversion had a related问题(不需要的隐式转换),但它仍然不适用。


为了完整起见,这里有一个稍微不那么简单但更具代表性的示例,说明我实际上正在做的事情,其目的是允许==为之工作thing<T,N> and thing<R,N>, 那就是N必须相同,但第一个模板参数可以不同。我将其包括在内,以防它影响可能的解决方案,因为这是我真正需要正确行为的:

template <typename T, int N> struct thing {
  operator const char * () const { return nullptr; }
  template <typename R> bool operator == (const thing<R,N> &) const { return false; }
};

int main () {
  thing<int,0> i0;
  thing<float,0> f0;
  thing<int,1> i1;
  i0 == f0;
  f0 == i0;
  i0 == i1; // should fail to compile
  f0 == i1; // should fail to compile
  i1 == i0; // should fail to compile
  i1 == f0; // should fail to compile
}

您只需提供一个deleted 版本的操作符,用于它不应该工作的情况,例如:

template <int N> struct thing {
  operator const void * () const { return nullptr; }
  bool operator == (const thing<N> &) const { return false; }
  template <int X>
  bool operator == (const thing<X> &) const = delete;
};

int main () {
  thing<0> a;
  thing<1> b;
  a == a; // This compiles
  a == b; // Doesn't compile
}

使用 C++20,逻辑还可以方便地扩展到operator!=。对于 C++20 之前的编译器,您可能应该添加相应的重载operator!=, too.

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

仅防止二元运算符的隐式转换运算符 的相关文章

  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反

随机推荐

  • 使用cv2.imread:“ returned NULL without set an error”,好像无法打开图片或获取数据

    这是我的代码中出现问题的部分 它应该计算图片中绿色像素的数量 img Image open path tif BLACK MIN np array 0 20 20 np uint8 BLACK MAX np array 120 255 25
  • 如何记录 PostgreSQL 查询?

    如何启用 PostgreSQL 8 3 执行的所有 SQL 的日志记录 已编辑 更多信息 我改变了这些行 log directory pg log log filename postgresql Y m d H M S log log st
  • Eclipse:更改ctrl+shift+/的块注释样式

    The keyboard shortcut ctrl shift produces comments in the format of comment 如何更改快捷方式 以便在星号前后添加空格 comment 非常感谢 I m afraid
  • 如何在 Node.js 中列出 cloudinary 文件夹中的所有图像/视频?

    我是新手Node js 我已经开始通过克隆来构建一个应用程序云数示例项目来自github https github com cloudinary cloudinary npm 然后我将工作目录更改为 photo album 并安装了应用程序
  • 将txt文件的内容分解为数组

    我在分解 txt 文件的内容时遇到问题 结构如下 01Name 1 02whatever contents 03whatever contents 01Name 2 02whatever contents 03whatever conten
  • 将变量从 flash 传递到 HTML/php

    我希望也许有人可以对我很难决定如何解决的问题提供一些见解 我有一个相当简单的 Flash 应用程序 用户可以在连接时快速创建一个用户名 并且该用户名是在 Flash swf 内创建的 现在 我有一个 cron 作业 每十分钟删除一次不活动的
  • 用于 bean 验证的自定义验证消息

    我正在创建一个 JSF 2 应用程序 并且尝试在 bean 中而不是 faces page 中使用表单验证 我还想使用 properties 文件来存储消息 我在看这个问题 https stackoverflow com questions
  • 卸载后取消 Redux 操作

    我想在组件卸载后取消一些功能 因为它会导致内存泄漏我的代码如下所示 componentDidUpdate prevProps if prevProps org org this props org org this mounted this
  • 如何使用 Perl SOAP 获取 JIRA 中的自定义字段列表?

    我很好奇是否有其他人知道如何获取您在 JIRA 中创建的所有自定义字段的列表 如果是这样 你是怎么做到的 我一直在尝试使用我在上找到的 Perl SOAP 例程JIRA SOAP 服务文档 http docs atlassian com s
  • Phonegap - 无法从服务器下载存档

    我正在尝试从我的 Phonegap Developer 应用程序运行电话间隙应用程序 但出现错误 无法从服务器下载存档 我正在连接到电话间隙桌面应用程序中显示的 IP 地址 PhoneGap 桌面应用程序显示消息 服务器正在运行http 1
  • 使用自定义键进行数组拼接

    假设我有这个代码 test array test zero abc test two ghi test three jkl dump test array splice test 1 0 def dump test 这给了我输出 Array
  • EF Core 中的 modelBuilder.Configurations.AddFromAssembly

    In EntityFramework 6 x 如果我们有很多EntityConfiguration那么我们可以将它们全部分配给OnModelCreating ModelBuilder modelBuilder 不一一列举如下 protect
  • MVC RadioButtonFor 组

    我有一个 PDF 课程 public class UIClonePDFDetail public int CatalogueID get set public List
  • 通过 API 在我的 Android 应用程序中查看 Excel 文件

    我想在我自己的 Android 应用程序中查看 Excel 文件 目前 使用我的应用程序我可以看到所有谷歌文档 但是在单击任何一个文档 例如 Excel 文件 myDemo xls 后 我想在我自己的应用程序中打开它 用于查看目的 我读过关
  • 使用 Python Paramiko 在不同的 SSH 服务器中并行运行多个命令

    我有一个SSH py目标是通过 SSH 连接到许多服务器来运行 Python 脚本 worker py 我正在使用 Paramiko 但对它非常陌生 并且不断学习 在我通过 ssh 连接的每台服务器上 我需要保持 Python 脚本运行 这
  • 如何使用 ASP.NET 5 MVC 6 保护 Web API

    我有一个很好的 ASP NET 5 MVC 6 应用程序正在运行 本质上 出于此目的 它只是您在启动新项目时获得的普通示例应用程序 以保持简单 到目前为止我可以 注册用户 Login Logout 保护页面 强制登录等 现在 我想要的是为应
  • “venv activate”不会改变我的Python路径

    我创建了一个虚拟环境 假设 test venv 我激活它 一切成功 然而 Python 解释器的路径不会改变 我已经在下面说明了这种情况 为了澄清起见 python 路径应该是 Desktop test venv bin python gt
  • .NET System.Text.Decoder.Convert 方法在字符中间返回completed==true

    我需要从 UTF 8 字节序列中读取一个字符串 这些字节的来源来自单独的读取操作 这些操作不考虑字符边界 因此我无法使用 System Text Encoding UTF8 GetString 但是 由 System Text Encodi
  • x86汇编代码的语法

    我试图了解操作系统的基础知识 并在 OCW 中找到了相关课程 名为 6 828 我在课程的实验室中找到了引导加载程序的代码 我尝试了但不明白以下部分代码 Enable A20 For backwards compatibility with
  • 仅防止二元运算符的隐式转换运算符

    我遇到了一个问题 我已将其归结为以下问题 其中 即使应该失败 运算符用法也会编译 C 17 在 GCC 5 x 8 x 和 9 x 上测试 template