【问题标题】:Legacy standard C library headers and overloaded C++ functions旧版标准 C 库头文件和重载的 C++ 函数
【发布时间】:2014-11-06 23:33:10
【问题描述】:

C++ 语言标准在 D.5

中说

2 每个 C 标头(每个标头都有一个 name.h 形式的名称)的行为 好像每个名称都由 对应的cname 标头放置在全局命名空间内 范围。未指定这些名称是首先声明还是 在命名空间 std 的命名空间范围 (3.3.6) 内定义,并且是 然后通过显式注入全局命名空间范围 使用声明(7.3.3)。

3 [示例:标题<cstdlib> 确保在 命名空间std。它还可以在全局范围内提供这些名称 命名空间。标题<stdlib.h> 肯定提供相同的 全局命名空间中的声明和定义,就像在 C 标准。它还可以在命名空间中提供这些名称 std。 —结束示例]

这似乎相当明确地声明(“...每个名称...”,“...相同的声明...”)旧式 <name.h> 标头必须提供与新样式的<cname> 标头,但在全局命名空间中。例如,各种 C 函数的 C++ 特定重载版本也不例外。

这似乎意味着<math.h> 必须在全局命名空间中提供sin 函数的三个版本:sin(float)sin(double)sin(long double)。反过来,这意味着以下 C++ 代码应该无法通过重载解析

#include <math.h>

int main() {
  sin(1);
}

在 MSVC++ 编译器下确实失败,但在 GCC 和 Clang 下编译成功。那么,GCC 是否只是忽略了关于已弃用的旧式标头的标准要求?还是我以某种方式误解了标准中的措辞?

【问题讨论】:

  • 第 17.6.2.3.1 节允许实现将 extern "C" 链接到使用外部链接声明的 C 标准库中的名称(尽管它建议不要这样做)。如果一个实现这样做了,它就不能定义三个不同版本的sin()
  • 我想你的意思是说 必须提供三个版本。 . .因为 math.h 是 C 头文件。因此,考虑到这一点,不会有任何过载问题,因为只有一个 sin 版本,但 std::sin 有三个。
  • @iheanyi:头文件可以很容易地在 C 和 C++ 之间进行交叉编译。如果没有其他办法,#ifdef __cplusplus 总是可以挽救这一天。
  • 是和不是。您不能包含 然后使用 std::sin,因为它在 math.h 中不存在。 #ifdef __cplusplus 与否。
  • @iheanyi:呃……这和std::sin有什么关系?首先,问题是关于math.h 中的sin,而不是关于std::sin。其次,即使不是主题,C++ 标准实际上声明math.h允许在命名空间std 中额外提供这些名称(参见上面的标准引用)

标签: c++ legacy standard-library


【解决方案1】:

感谢@hvd 的 cmets,我看到了曙光,事实证明 MSVC 是正确的,GCC 也应该抱怨歧义。

包含&lt;cmath&gt;&lt;math.h&gt; 之间的唯一区别是名称最初的作用域,前者在namespace std 中,后者在全局命名空间中(实现可以在其他命名空间也是如此,但这不是强制性的),并且不推荐包含 C 标头的 .h 变体这一事实。

【讨论】:

  • 是的,但这与 D.5 所说的有何一致?它基本上说math.h 必须提供与cmath 相同的声明。
  • @AndreyT [headers] "4 除第 18 到 30 条和附件 D 中的说明外,每个 header cname 的内容应与相应 header 的内容相同名称.h,[...]”。我猜 D.5 中的措辞是模棱两可的。
  • @AndreyT 想一想,这并不模棱两可:In addition to the double versions of the math functions in &lt;cmath&gt; 从技术上讲,重载根本不是&lt;cmath&gt; 的一部分。我猜它们被预处理器精灵神奇地包含了。
  • 一点也不模棱两可,也没有说你说的是什么。 C 在&lt;math.h&gt; 中指定double sin(double);。 C++ 指定&lt;cmath&gt; 类似于C 的&lt;math.h&gt;,除了double 版本之外,它还添加了float sin(float);long double sin(long double);。然后 C++ 指定 &lt;math.h&gt; 类似于 C++ 的 &lt;cmath&gt;,只是名称是在全局命名空间中声明的。没有任何迹象表明 C++ 的 &lt;math.h&gt; 与 C 的 &lt;math.h&gt; 匹配。 C++ 的 &lt;math.h&gt; 需要提供这些覆盖,除非您可以在标准中找到明确的声明。
  • @hvd 正如我的第二条评论指出的那样,重载听起来并不是&lt;cmath&gt; 的一部分。当然,措辞应该是“除了标准 C 库头文件 中的数学函数的双重版本之外”吗?
猜你喜欢
  • 1970-01-01
  • 2022-12-05
  • 2016-08-23
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多