vit*_*aut 10 c++ gcc compiler-errors cmath c++11
既然isnan可以是宏(在C++ 98中)或在命名空间std中定义的函数(在C++ 11中),这个简单的例子说明了编写在两种情况下都有效的代码的明显(并且可能是天真的)方式.
#include <cmath>
int main() {
double x = 0;
using namespace std;
isnan(x);
}
Run Code Online (Sandbox Code Playgroud)
但是,编译它会在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)
^
Run Code Online (Sandbox Code Playgroud)
为什么在C++ 11中这是不明确的,以及如何使它适用于C++ 98和C++ 11,最好不需要太多的条件编译?
Sha*_*our 12
这是一个libstdc++错误报告中记录的错误std函数与C函数冲突时使用c ++ 0x支持(并使用命名空间std)和一个非常类似于OP的再现示例:
#include <stdlib.h>
#include <cmath>
#include <stdio.h>
using namespace std;
int main(int argc, char** argv)
{
double number = 0;
if (isnan(number))
{
printf("Nan\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
其中一条评论说:
我不认为这是问题所在,因为libstdc ++总是在全局命名空间中声明名称,即使它在C++ 03中无效 - 我们没有为C++ 0x更改它(所有发生的事情都是放宽标准以反映实际实施的现实)
这可能最终得到解决,直到那时bug报告提供的解决方案如下:
通过调用:: isnan或std :: isnan来明确限定isnan
使用::isnan尽可能我可以告诉作品预C++ 11和C++中11.
当然这是一个libstdc++特定的解决方案,它看起来也很有效,libc++但如果你需要支持一个不起作用的编译器,你可能不得不求助于使用#if/#else.
注意,如具有isnan标记的constexpr 的MM表示不符合,这也是已知问题,尽管它对该特定问题没有贡献.
另请参阅相关的错误报告:[C++ 11]重载'isnan'的调用是不明确的,并使用bool返回类型识别内置函数.第二部分讨论可能的libstdc++解决方
更新
如果你想要一个gcc/clang解决方案,看起来它们都支持__builtin_isnan,请参阅内置的gcc文档以获取更多信息.另请参阅这个glibc 错误报告,用内置替换isnan等.
在考虑了一段时间之后,我认为在C ++ 11之前根本没有可移植的方法来执行此操作。C isnan宏是在C99中引入的,但是C ++ 98和C ++ 03是基于C89的。因此,如果您依靠C ++ 98/03的实现拖入提供isnan(顺便说一句,这是不合格的)C99标头,则无论如何您都在做出不可移植的假设。
然后unsing,用using声明替换该指令,将为您提供以下代码,这些代码是可移植的C ++ 11(也可解决libstdc ++的缺陷),并且可能适用于较早实现的情况。(无论它们isnan是作为全局宏提供还是作为函数提供namespace)。
template <typename T>
bool
my_isnan(const T x)
{
#if __cplusplus >= 201103L
using std::isnan;
#endif
return isnan(x);
}
Run Code Online (Sandbox Code Playgroud)
将其包装在其自身的功能中似乎可以#if接受。
| 归档时间: |
|
| 查看次数: |
10672 次 |
| 最近记录: |