-O1/2/3与-std=c++1y/11/98一起使用时,如果包含<cmath>,则会出现错误:在此范围内未声明“_hypot”。

9

我刚刚使用 mingw-get-setup 更新了 MinGW,如果我在使用 -std=c++1y 以及大于 -O0 的参数时,无法构建任何包含 <cmath> 头文件的东西。(我也尝试过 c++11c++98)我会得到像这样的错误:

g++.exe -pedantic-errors -pedantic -Wextra -Wall -std=c++1y -O3  -c Z:\Projects\C++\L6\src\events.cpp -o obj\src\events.o
In file included from z:\lander\mingw\lib\gcc\mingw32\4.8.1\include\c++\cmath:44:0,
                 from Z:\Projects\C++\L6\src\utils.h:4,
                 from Z:\Projects\C++\L6\src\events.cpp:10:
z:\lander\mingw\include\math.h: In function 'float hypotf(float, float)':
z:\lander\mingw\include\math.h:635:30: error: '_hypot' was not declared in this scope
 { return (float)(_hypot (x, y)); }

我的电脑出了问题吗?
还是mingw仓库的版本有bug?如果是这样,是否有快速修复此头文件的方法?


你尝试在"g++"命令行的末尾添加"-lm"了吗? - Keith Thompson
@KeithThompson 同样的错误。你能重现它吗? - HolyBlackCat
这个问题是否发生在任何包含 #include <cmath> 的程序中,还是只有调用 hypot() 函数的程序中才会出现? - Keith Thompson
@KeithThompson 任何包含 #include <cmath> 的程序。 - HolyBlackCat
@KeithThompson 在MinGW中-lm是多余的;libm.a实际上是一个空档案,数学功能由默认的C运行时库提供(可以是Microsoft的MSVCRT.DLL本身,也可以是MinGW.org的libmingwex.a扩展库,两者都是默认搜索的)。 - Keith Marshall
3个回答

15
为了避免任何进一步的猜测和彻底的不良建议,例如使用#if 0,让我从一个MinGW项目贡献者的角度给出权威答案。是的,MinGW.org的include/math.h实现确实存在一个错误,在编译C++时会触发该错误,并且在包括受影响的头文件(如包括cmath时)的情况下指定任何导致__STRICT_ANSI__变为定义的编译器选项时也会触发该错误(例如OP指出的那些-std=c...选项)。适当的解决方案不是通过使用#if 0或其他方式来遮蔽math.h文件的部分内容,而是修正hypotf (float, float)的损坏的内联实现;只需从内联引用中删除虚假的前导下划线,其中它的返回值被强制转换为浮点返回类型即可。或者,在编译器选项中将等效的-std=gnu...替换为-std=c...可以绕过错误,并可能提供适当的解决方法。顺便说一句,我对MinGW.org当前的hypotl (long double, long double)实现并不完全满意;纠正这两个问题在下一个MinGW运行时的发布清单上,但目前我没有太多时间准备这个。更新:此错误已不再存在于MinGW.org运行时库的当前版本(当前为mingwrt-3.22.4,但自发布3.22以来已修复)。如果您使用的是任何早于此版本的内容(包括任何严重损坏的4.x版本),则应进行升级。

或者,用等效的-std=gnu...替换-std=c...,那么你是说用-std=gnu++0x替换-std=c++0x吗? - Scorb
@ScottF:“_你是说用-std=gnu++0x替换-std=c++0x吗?_” 是的,就是这样。其效果是启用相应-std=c...选项的语义(如果这很重要),但是不会抑制GNU扩展,特别是避免指定__STRICT_ANSI__ - Keith Marshall

2
正如 Keith 所指出的那样,这是 MinGW.org 头文件中的一个 bug。
作为编辑 MinGW.org 头文件的替代方案,您可以使用 MinGW-w64,它提供了 MinGW.org 提供的所有内容以及更多的功能。有关运行时之间差异的列表,请参见 此维基页面

1
MinGW使用gcc和Microsoft运行时库。 Microsoft的实现支持C90,但其对C标准的后续版本(C99和C11)的支持非常差。 hypot函数(以及hypotfhypotl)是在C99中添加的。
如果您正在使用调用hypot的程序而出现此错误,例如:
#include <cmath>
int main() {
    std::cout << std::hypot(3.0, 4.0)) << '\n';
}

如果发生在任何具有#include <cmath>的程序中,那么这只是Microsoft运行时库和MinGW的限制,因此是一个错误,可能是MinGW的配置错误。

1
上面的测试程序如果想要调用未经限定的 hypot 函数,应该包含 <math.h> 头文件。 - Jonathan Wakely
@JonathanWakely: 我将其更改为 std::hypot - Keith Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接