变量的 cmath 和 y0 名称未编译

cmath and y0 name of variable not compiling

我得到了名为 y0 的变量并包含了 cmath,当使用没有任何参数的 g++ 编译它时,出现编译错误

error: invalid operands of types ‘double(double) throw ()’ and ‘double’ to binary ‘operator+’ y = y0 + R; ~~~^~~

为了实验,我删除了 cmath 包括并且一切编译正常。

#include <iostream>
#include <cmath>

double y0, y, R;
int main() {
    std::cin >> y0 >> R; 
    y = y0 + R;
}

您使用的编译器 g++ 是 unconditionally defining the macro _GNU_SOURCE. The macro _GNU_SOURCE is working according to man feature_test_macros 。该宏导致 GNU C 库实现 glibc 定义了许多额外的 gnu 扩展,这些扩展污染了全局命名空间。在 glibc 中,包含文件 cmath 包含 math.h.

这些 gnu 扩展之一是例如 double y0(double) 函数,它是计算贝塞尔函数的 gnu 扩展。如果您尝试在全局命名空间中将您自己的 y0 符号声明为不同的符号,编译器应该抱怨为 y0 符号声明的类型冲突。您看到的错误之一是因为符号 y0 被声明为函数,所以编译器无法 + 添加它。

正确的解决方法是正确解决 glibc 中的混乱并帮助世界各地的开发人员 - 修补 glibc 和 g++ 在用 c++ 编译时不要导出 gnu 扩展函数。仍然如 libstdc++ faq 所示:We'd like to find a cleaner solution, but nobody yet has contributed the time.

另一种解决方法是使用 -U_GNU_SOURCE 编译器开关取消定义 g++ 中的 _GNU_SOURCE 符号。这可能会在使用时导致有关数学模板函数中未声明符号的错误,因为 glibc/libstdc++ 中的许多数学函数实现使用 gnu 扩展。另一个解决方法是使用另一个不会遇到此问题的标准 C++ 库实现。

一个现实的解决方法是不在全局命名空间中声明 y0 符号。只需在周围添加一个命名空间并正确引用它即可:

namespace my {
   double y0;
}
int main() { 
   my::y0 = 1;
}