【问题标题】:Why is abs not in std?为什么 abs 不在标准中?
【发布时间】:2021-08-06 21:05:18
【问题描述】:
#include <cmath>
int abs;
int main()
{

}

这段代码抛出编译错误

error: 'int abs' redeclared as different kind of symbol
note: previous declaration 'int abs(int)'

如果我从cstdlib 包含它,也会发生同样的事情。

我阅读了这份文档https://en.cppreference.com/w/cpp/numeric/math/abs 这里没有提到abs 将在std 之外定义。事实上,它到处都明确提到它为std::abs

其他函数也会发生同样的情况,例如sqrt

为什么会这样?如何在不弄乱我的命名空间的情况下使用这些功能?如果不可能,有 c++ 替代品吗?

【问题讨论】:

  • 在 C++ 之前,有 C。
  • 这个问题似乎与链接的副本不同。或者我没有看到重复中​​的哪个答案回答了这个问题。
  • c++ 实现必须有 std::abs 没有什么能阻止他们在全局命名空间中声明 abs
  • 标准要求这些可以在命名空间std中访问,但不要求它们不被添加到全局命名空间中。
  • @FrançoisAndrieux -- 规则是&lt;cxxx&gt; 标头是必需 来声明命名空间std 内的所有相应C 函数并且是允许的 也将它们放在全局命名空间中。同样的事情,相反,&lt;xxx.h&gt; 标头:它们需要将名称放在全局命名空间中,并且允许也将名称放在 @ 987654335@命名空间。

标签: c++


【解决方案1】:

为什么abs不在std中?

你的问题有点错误。 abs std 中。假设您在问“为什么 abs 在全局命名空间中?”

除了在std 命名空间中声明之外,C++ 标准还允许在全局命名空间中声明 C 标准函数。

为什么会这样?

因为这些函数来自 C 标准库,并且因为标准允许它发生,并且因为您的标准库的实现方式。

如何在不弄乱我的命名空间的情况下使用这些函数?

这些名称保留给全局命名空间中的语言实现。没有办法避免。

不要将全局命名空间视为“您的命名空间”。全局命名空间很混乱,而且永远都是。你需要解决这个问题。

如果不可能,有 c++ 替代品吗?

C++ 替代方法是在 your 命名空间中声明 your abs

namespace my_very_own_namespace {
    int abs;
}

您应该在自己的命名空间中声明所有内容1,除了:

  • 那个命名空间本身
  • main
  • 允许的其他命名空间中名称的模板特化
  • 跨语言 API,即任何东西 extern "C"

最难的部分是为自己的命名空间找出一个唯一的名称,因为它不能是 C 标准库已经使用的名称,也不能是全局命名空间中其他库使用的任何名称。

1 在编写小型练习程序等时几乎不需要遵循这个经验法则。但是在编写大型程序和依赖第三方库时就变得必不可少,更不用说在为他人编写这些库时使用。


标准引号:

[extern.names]

使用外部链接声明的 C 标准库中的每个名称都保留给实现,用于在命名空间 std 和全局命名空间中用作具有外部“C”链接的名称。

使用外部链接声明的 C 标准库中的每个函数签名都保留给实现,以用作具有 extern "C" 和 extern "C++" 链接的函数签名,171 或作为全局命名空间范围的名称命名空间。

[标题]

除了[library] 到[thread] 和[depr] 中的说明外,每个头文件cname 的内容与C 标准库中指定的相应头文件name.h 的内容相同。 然而,在 C++ 标准库中,声明(在 C 中定义为宏的名称除外)在命名空间 std 的命名空间范围内。 未指定这些名称(包括在 [support] 中通过 [thread] 和 [depr] 添加的任何重载)是否首先在全局命名空间范围内声明,然后通过显式使用声明([namespace.udecl] )。

【讨论】:

    猜你喜欢
    • 2021-05-07
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    相关资源
    最近更新 更多