【发布时间】:2016-02-19 14:48:35
【问题描述】:
由于isnan 可以是宏(在 C++98 中)或在命名空间 std(在 C++11 中)中定义的函数,因此这是编写有效代码的一种明显(也可能是幼稚的)方式这个简单的例子说明了这两种情况
#include <cmath>
int main() {
double x = 0;
using namespace std;
isnan(x);
}
但是,编译它会在 GCC(使用 -std=c++11)和 Clang 中产生错误:
test.cc: In function ‘int main()’:
test.cc:6:10: error: call of overloaded ‘isnan(double&)’ is ambiguous
isnan(x);
^
test.cc:6:10: note: candidates are:
In file included from /usr/include/features.h:374:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
from /usr/include/c++/4.8/cmath:41,
from test.cc:1:
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:234:1: note: int isnan(double)
__MATHDECL_1 (int,isnan,, (_Mdouble_ __value)) __attribute__ ((__const__));
^
In file included from test.cc:1:0:
/usr/include/c++/4.8/cmath:626:3: note: constexpr bool std::isnan(long double)
isnan(long double __x)
^
/usr/include/c++/4.8/cmath:622:3: note: constexpr bool std::isnan(double)
isnan(double __x)
^
/usr/include/c++/4.8/cmath:618:3: note: constexpr bool std::isnan(float)
isnan(float __x)
^
为什么这在 C++11 中是模棱两可的,如何让它在 C++98 和 C++11 上都可以工作,最好不用太多的条件编译?
【问题讨论】:
-
当然。我添加了完整的可编译示例
-
如果写
(isnan)(x);还是报错,那就和宏无关 -
我在 Windows 的 g++ 4.9.2 中没有得到错误,但是在使用某种 Linux 的 Godbolt 上得到了它。所以也许这是 glibc 头文件中的一个错误
-
std::isnan(long double)和std::isnan(float)也被列出了一些错误,因为它们无论如何都不能被选中;歧义在::isnan(double)和std::isnan(double)之间 -
@JohnDrouhard 好点,真正的错误是有两个不同的功能。 C++ 标准要求如果存在
::isnan,则std::isnan必须是注入命名空间std 的相同函数。 C++ 库应该使用 C 库的isnan(double)并仅添加std::isnan(long double)和std::isnan(float)。
标签: c++ c++11 gcc compiler-errors cmath