isnan 是否在 std:: 命名空间中?更一般地说,何时是 std::必要、可选或要避免
Is isnan in the std:: namespace? More in general, when is std:: necessary, optional or to be avoided?
在 Mingw 4.7.2 中,我有一个由于调用 isnan
而无法编译的库。如果我使用 std::isnan
,编译器会说"一切都会好起来的",而且我确实设法编译了我的文件。
但是如果我在这里检查(编辑:但也许我也应该在这里检查:-((,std::
似乎没有必要。如果我添加它,文件是否可移植?
更一般地说,对于每种情况,是否有一种通用方法来了解何时需要放置std::
(为了可移植性(、可选或避免?
编辑
事实上,问题的起源之一是有多个标头包含,并且一些包含的标头包含<cmath>
,而此cpp文件试图包含<math.h>
(当<cmath>
已被包含时(。
这取决于您包含的标头。如果包含 C 标头<math.h>
(它是C++的一部分,尽管标记为已弃用(,则可以使用非限定的 C 函数,如 isnan
。另一方面,如果您包含 C++ 标头<cmath>
,则只能保证它将<math.h>
中的所有函数带入std
命名空间,因此您必须正确限定它们,例如std::isnan
(或使用某种using
指令(。不幸的是,当包含<cmath>
时,也允许但不需要将这些函数引入全局命名空间(因此它是众多"在我的机器上工作">之一 - C++的发生率以及许多人编写代码的原因,就像你刚刚尝试编译失败一样
所以总结一下:要么包括<math.h>
并使用isnan
要么包括<cmath>
并使用std::isnan
,其他一切都是不可移植的。当然,所有这些都适用于任何其他 C 标头及其各自的 C++ 版本。
编辑:应该注意的是,这个特定的功能isnan
仅从C++11开始受支持,并且在C++98中根本不可用(这可能是您混淆的一部分(。但这在这种情况下不会改变任何事情,因为在 C++98 中,<cmath>
和 <math.h>
(这是当时实际的 C89/C90 标头,而不是 C++11 包含的 C99 标头(都没有此功能,因为它们始终同步。因此,您问题中的这个库可能尝试的是使用 C++98,同时从不同的 C99 实现中获取isnan
函数(这不是一个特别好的主意,因为它可能与 C++ 实现的 C89/C90 部分冲突,甚至从未尝试过这个(。
C 没有命名空间的概念。当你写#include <math.h>
头中声明的所有名称都会进入全局命名空间,你需要写isnan
。
C++具有命名空间。尽管如此,当你写#include <math.h>
标头中声明的所有名称都会进入全局命名空间,你需要写isnan
,就像在 C 中一样。
此外,当你写#include <cmath>
标头中声明的所有名称都会进入命名空间std
,你需要写std::isnan
。
此外,C++实现也可以走另一条路,#include <math.h>
将名称放入std
和全局命名空间中,#include <cmath>
将名称放入全局命名空间以及std
中。不要依赖这个;这样做的代码不可移植。这是对实施者的让步,使事情变得更容易;它的真正含义是,如果您使用#include <cmath>
则不能假设全局命名空间中不会有isnan
,并且如果您使用#include <math.h>
则不能假设std
中不会有isnan
。
那是因为isnan
来自C.使用不同类型的include
会导致不同的结果。以 C 标头<math.h>
中的isnan
为例:
如果使用 #include <cmath>
,它将放在 std
命名空间中。
如果使用 #include <math.h>
,它将放在全局命名空间中。
C++11 D.5 C 标准磁带库接头
每个 C 标头(每个标头都有一个 name.h 形式的名称(的行为就像由相应的 cname 标头放置在标准库命名空间中的每个名称都放置在全局命名空间范围内一样。未指定这些名称是首先在命名空间 std 的命名空间范围 (3.3.6( 内声明或定义,然后通过显式 using-声明 (7.3.3( 注入全局命名空间范围。
[ 示例:标头确保在命名空间 std 中提供其声明和定义。它还可以在全局命名空间中提供这些名称。标头确保在全局命名空间中提供与 C 标准相同的声明和定义。它还可能在命名空间 std 中提供这些名称。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 是否有必要使用 std::move?这不是已经是一个右值参考了吗?
- std::mutex::lock() 产生奇怪(和不必要的)ASM 代码
- 避免使用std::unordered_map(和其他)进行重复搜索或不必要的构造
- 如果有专门的函数和模板化的函数,为什么没有必要专门针对"std::nullptr_t"
- C++填充一个std::map创建不必要的对象
- 如有必要,如何让 std::endl 输出"rn"?
- 如何避免不必要的 std::vector<Base *> 的构造
- 当我<exception>似乎可以使用 std::exception 时,即使它不包括在内,是否有必要 #include?
- 在向线程传递引用时,std::ref真的是必要的吗
- 为什么std::move之后的析构函数调用是必要的
- 当将昂贵的对象存储在一对中时,是否有必要进行 std::move
- 不必要的 std::在 cpp 首选项示例中result_of向前使用
- C++11:std的微妙之处::转发:身份真的有必要吗?
- 通过使用不同的参数调用每个元素的非默认构造函数来初始化std::vector,而不需要进行不必要的复制
- isnan 是否在 std:: 命名空间中?更一般地说,何时是 std::必要、可选或要避免
- 在lambda中放入std::move真的有必要吗?
- 在向std::unordered_map插入元素时避免不必要的构造函数调用