将非算术类型作为参数传递给 cmath 函数是否有效?

2024-05-09

给定以下用户定义类型S具有转换功能double:

struct S
{
   operator double() { return 1.0;}
};

以及以下调用cmath http://en.cppreference.com/w/cpp/header/cmath使用类型的函数S:

#include <cmath>

void test(S s) {
   std::sqrt(s); 
   std::log(s); 
   std::isgreater(s,1.0);
   std::isless(s,1.0);
   std::isfinite(s) ;
}

这段代码编译时使用gcc using libstdc++ (现场观看 http://melpon.org/wandbox/permlink/15CSejElegZAf85f)但与clang using libc++它会为几个调用生成错误(现场观看 http://melpon.org/wandbox/permlink/ImDK79QNvnVG0hnn) 并出现以下错误更伟大 http://en.cppreference.com/w/cpp/numeric/math/isgreater:

error: no matching function for call to 'isgreater'
   std::isgreater(s,1.0);
   ^~~~~~~~~~~~~~

note: candidate template ignored: disabled by 'enable_if' [with _A1 = S, _A2 = double]
std::is_arithmetic<_A1>::value &&
^

和类似的错误isless http://en.cppreference.com/w/cpp/numeric/math/isless and isfinite http://en.cppreference.com/w/cpp/numeric/math/isfinite, so libc++期望这些调用的参数是算术类型 http://en.cppreference.com/w/cpp/types/is_arithmetic which S不是,我们可以通过访问源来确认这一点libc++ cmath 标头 https://github.com/llvm-mirror/libcxx/blob/0b6f8ed1c772afbdb2c28451e67ac5ee7b6092fe/include/cmath。尽管所有算术类型的要求并不一致cmath功能于libc++.

所以问题是,将非算术类型作为参数传递给cmath功能?


TL;DR

根据标准,将非算术类型作为参数传递给cmath功能正常但有缺陷报告2068认为最初的意图是cmath函数应仅限于算术类型,并且使用非算术参数似乎最终可能会导致格式错误。因此,尽管从技术上来说,使用非算术类型作为参数是有效的,但根据缺陷报告,这似乎是有问题的2068.

Details

The cmath http://en.cppreference.com/w/cpp/numeric/math标准草案部分涵盖了标头26.8 [c.math]提供了额外的float and 长双中定义的每个函数的重载math.h http://en.cppreference.com/w/c/numeric/math这需要一个double论证和进一步的段落11足够的过载并说:

此外,还应有足够的额外过载,以确保:

  1. 如果与 double 参数对应的任何参数的类型为 long double,则与 double 参数对应的所有参数都是 有效地转换为长双倍。
  2. 否则,如果对应于 double 参数的任何参数具有 double 类型或整数类型,则对应于的所有参数 double 参数被有效地转换为 double。
  3. 否则,与双参数相对应的所有参数都将有效地转换为浮点型。

这在 C++11 中似乎有效

在 C++11 部分26.8 [c.math]不包括任何不允许非算术参数的限制cmath功能。在问题的每种情况下,我们都有一个可用的重载,需要double参数,这些应该通过选择过载解析 http://en.cppreference.com/w/cpp/language/overload_resolution.

缺陷报告2086

但对于 C++14 我们有缺陷报告 2086:对数学函数的过于通用的类型支持 http://cplusplus.github.io/LWG/lwg-defects.html#2086,它认为该节的初衷26.8 [c.math]是为了限制cmath函数仅适用于算术类型,这会模仿他们的工作方式C:

我的印象是这个规则集可能更通用 有意的,我的假设是它是为了模仿 C99/C1x 而编写的 7.25 p2+3 中以“C++”方式设置的规则 [...](请注意,C 约束 C++ 描述为算术类型的有效类型集,但请参阅 下面是一个重要的区别)[...]

并说:

我目前解决这些问题的建议是限制 这些函数的有效参数类型为算术类型。

和改写的部分26.8段落11说(强调我的):

此外,还应有足够的额外过载,以确保:

  1. If any 算术对应于 double 形参的实参的类型为 long double,那么所有算术参数对应于 double 参数有效地转换为 long double。
  2. 否则,如果有的话算术对应于 double 参数的 argument 类型为 double 或整数类型,则所有算术对应于双参数的参数被有效地转换为 双倍的。
  3. Otherwise, all arithmetic arguments corresponding to double parameters are effectively cast to are effectively cast to have type float.

那么这在 C++14 中是无效的吗?

好吧,尽管有这样的意图,但正如讨论中的评论中所述,它在技术上看起来仍然有效libc++ 错误报告:isnan 和类似函数的错误实现 https://llvm.org/bugs/show_bug.cgi?id=18218#c8:

这可能是意图,但我看不到任何方式来阅读 标准的措辞就是这样。从 comment#0 中的示例来看:

std::isnan(A());

没有算术类型的参数,因此没有任何项目符号 26.8/11 适用。重载集包含'isnan(float)'、'isnan(double)'和'isnan(long double)',并且'isnan(float)'应该 被选中。

因此,改写为DR 2086段落的11不会使调用格式不正确float, double and 长双否则可使用非算术参数重载。

技术上有效,但使用起来有问题

所以虽然C++11和C++14标准不限制cmath算术参数的函数DR 2068争论的意图26.8段落11是为了限制cmath函数只接受算术参数,显然是为了弥补 C++14 中的漏洞,但没有提供足够强的限制。

依赖一个在标准的未来版本中可能会变得不正确的功能似乎是有问题的。由于我们存在实现分歧,因此任何依赖于将非算术参数传递给的代码cmath这些情况下的功能是不可移植的,因此仅在有限的情况下有用。我们有一个替代解决方案,即显式地将非算术类型转换为算术类型,这绕过了整个问题,我们不再需要担心代码格式错误,而且它是可移植的:

std::isgreater( static_cast<double>(s) ,1.0)
                ^^^^^^^^^^^^^^^^^^^^^^

正如 Potatoswatter 指出的那样,使用一元+也是一个选项:

std::isgreater( +s ,1.0)

Update

作为 T.C.在 C++11 中指出,可以说26.8段落11 bullet 3适用,因为参数既不是长双, double也不是整数,因此应该是类型的参数S应该投射到float第一的。注意,如缺陷报告所示gcc从未实施过这个,据我所知也没有实施过clang.

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

将非算术类型作为参数传递给 cmath 函数是否有效? 的相关文章

随机推荐

  • 有没有任何工具可以将 PVR 纹理分割成一组图块?

    我有一张大的 png 纹理 4096x4096 我需要将其部分加载到内存中 我已经将大 png 纹理分割成 16 个 1024x1024 块 然后将它们转换为 PVR 压缩文件 问题是 当我绘制这些图块时 图块之间的边缘与 png 的边缘不
  • 使用 Flask-SQLAlchemy 进行多对多多数据库连接

    我正在尝试使这个多对多联接与 Flask SQLAlchemy 和两个 MySQL 数据库一起工作 并且它非常接近 只是它为联接表使用了错误的数据库 这是基础知识 我有main db and vendor db 表格设置为main db u
  • Flutter 分析/构建在 GitHub 操作中失败

    当运行以下操作时 它会失败flutter analyze 如果我删除它 稍后会失败flutter build 这两个命令在本地都可以正常工作 我理解该消息 但无法理解包路径可能有什么问题 GitHub 操作错误 flutter analyz
  • 如何在Webview中保存用户名和密码

    目前 我还在学习Android开发的过程中 所以如果我的这个问题对你来说不太容易理解 请原谅 我创建了一个 Android 应用程序 它使用 RecyclerView 显示一组列表 当用户单击列表中的每个名称时 它会将它们重定向到一组不同的
  • 我们可以使用 EWS 托管 API 连接到 Exchange 2016 吗?

    我使用的是 EWS 托管 API 2 2 它的枚举中没有显示 Exchange 版本 2016 我可以看到 Exchange 2013 之前的版本 那么如何连接到 Exchange Server 2016 该 API 是否尚未从 Micro
  • Android - 保持用户登录状态

    我正在尝试使用 PHP 和 MySQLi for Android 进行登录 我不明白的是如何保持用户登录状态 我看到一个简单的教程 其中有人使用 SQLite 来保护信息 但我不知道这是否真的安全 如何保存用户信息以保持用户登录状态 谢谢
  • 将enable_nestloop设置为OFF有哪些陷阱

    当我的表中有大量行时 我的应用程序中有一个查询运行得非常快 但是 当行数适中 既不大也不小 时 相同的查询运行速度会慢 15 倍 解释计划显示对中等规模数据集的查询正在使用嵌套循环其连接算法 大数据集使用散列连接 我可以阻止查询规划器在数据
  • MySQL 连接逗号分隔字段

    我有两张桌子 第一个表是batch在字段 batch 中包含逗号分隔的学生 ID 的表 batch id batch 1 1 2 2 3 4 第二个表是分数 marks id studentid subject marks 1 1 Engl
  • 注解和装饰器有什么区别?

    我很困惑何时使用术语注释以及何时使用装饰器 Component selector tabs template export class Tabs 装饰器对应于在类上调用的函数 而注释是使用 Reflect Metadata 库在类上设置的
  • 如何在 flutter 中用动画 POP

    我正在触发 Navigator pop 事件 并且想要淡出到页面的过渡 我尝试过 Fluro 但没有尝试过 我对实施它不感兴趣 这就是我正在做的 Widget build BuildContext context return Scaffo
  • “if”在 ASP.NET MVC View (.aspx) 文件中被认为有害?

    我记得看到一个博客 或其他内容 说你不应该在 ASP NET MVC 的 aspx 文件中使用 但我不记得它说的替代方案是什么 有人记得看过这个并指出我吗 基本上 这意味着您的视图中不应该有大量的 if 语句 您的控制器和视图模型应该能够处
  • 对数据框的行进行排序

    我有以下数据框 adjusted RFC df Node Feature Indicator Scaled Class Direction True False 0 0 km lt 0 181 class 4 0 gt 1 NA 125 1
  • 导入 CSS 文件时出现“找不到所需模块”的流程

    当我尝试通过 webpack import index css 导入 CSS 时 出现此错误 3 import index css index css Required module not found 我有一个类似 ComponentNa
  • jQuery 在提交的数据中附加一些奇怪的字符串

    重现该bug的代码 在html页面中放入以下代码并读取Fiddler中提交的数据 jQuery 1 4 2工作正常 问题发生在1 5 1和1 5 2
  • maven 构建 OSGi 的问题(包括依赖项)

    我目前正在从 OSGi iPOJO 和 iPOJO Annotations 开始 并尝试构建一个要在 Felix 中部署的简单组件 不幸的是 我遇到了各种问题 这些问题需要我花几个小时才能解决 或者在浪费时间后我什至无法解决 如下所示 我想
  • 通过 powershell 获取压缩的 TFS 2015 (vNext) 构建输出日志(就像构建后的下载链接一样)

    我想知道是否有人有一个 PowerShell 脚本 可以通过 TFS 2015 vNext 的 Rest API 下载此构建 ID 的所有当前构建日志 直到当前步骤 为每个记录的构建步骤创建单独的文本文件 并压缩所有文本文件 或者 如果已经
  • 在React-native中,如何更改NavigatorIOS的样式

    在react native中 如何更改NavigatorIOS的样式 例如背景颜色 谢谢你 var speedNews React createClass render function return
  • 从 Activity 调用选项卡式片段方法

    我有一项活动由三个片段组成 这些片段使用使用 PagerAdapter 的操作栏选项卡 我想要做的是从主活动访问活动选项卡式片段中的方法 我已经尝试了下面的代码 但这只是将片段返回为空 所以我猜它无法在选项卡中找到它 NPListFragm
  • R markdown 引文标识符

    R markdown 允许使用 YAML 元数据部分中的参考书目元数据字段指定参考书目文件 例如 title Sample Document output html document bibliography bibliography bi
  • 将非算术类型作为参数传递给 cmath 函数是否有效?

    给定以下用户定义类型S具有转换功能double struct S operator double return 1 0 以及以下调用cmath http en cppreference com w cpp header cmath使用类型的