问题描述
我发现 MPFR C++ 的大精度代码非常有用,并且过去曾成功使用过。最近,在开发一个新的应用程序时,我在他们的头代码 (mpreal.h) 中遇到了大量的编译器错误。我已经确定了所有这些错误的原因:在 typedef 和函数名中都使用了一个名称,再加上一个不直观的宏结果。相关的宏在 mpfr 包中,发生在 mpfr 4.0.2-5 和 4.1.0-6 之间。我使用的是最新版本的 mpreal.h(版本 3.6.8),但其他早期版本的行为相同。
编译器错误有所不同,但以下是典型的:
In file included from mpreal.h:125:
mpreal.h:624:32: error: no matching function for call to ‘mpfr::mpreal::mpfr_srcptr(const __mpfr_struct*&)’
624 | mpfr_init2(mpfr_ptr(),mpfr_get_prec(u));
| ^~~~~~~~~~~~~
mpreal.h:324:19: note: candidate: ‘const __mpfr_struct* mpfr::mpreal::mpfr_srcptr() const’
324 | ::mpfr_srcptr mpfr_srcptr() const;
| ^~~~~~~~~~~
mpreal.h:324:19: note: candidate expects 0 arguments,1 provided
相关的代码行(除上述之外)是:
mpreal.h:125 #include <mpfr>
mpfr.h:866 #define mpfr_get_prec(_x) MPFR_VALUE_OF(MPFR_SRCPTR(_x)->_mpfr_prec)
mpfr.h:845 #define MPFR_VALUE_OF(x) (0 ? (x) : (x))
mpfr.h:847 #define MPFR_SRCPTR(x) ((mpfr_srcptr) (0 ? (x) : (mpfr_srcptr) (x)))
问题似乎出在第 847 行的宏中。出现在 MPFR_SRCPTR(x) 中的 (mpfr_srcptr) (x) 旨在将 x 类型转换为 mpfr_srcptr 类型,但被解释为表示 a使用参数 x 调用 mpfr_srcptr()。在宏之外,gcc 可以区分 (mpfr_srcptr)(x) 和 mpfr_srcptr(x) 之间的区别,但宏显然忽略了括号。谁能解释这种宏行为?我知道 gcc 有大量的开关来控制几乎所有东西,但是否有某个选项会影响宏中括号的解释?
我想这种行为可能是我的系统所独有的,但我觉得这很难相信。但我也发现很难相信社区其他人没有注意到这样的错误。我在网站或github上都没有发现任何问题的建议,该项目最近已转移到该项目。
解决方法
宏 SRCPTR 并没有像我原先想象的那样忽略括号;该行为由范围的差异来解释。 SRCPTR 宏虽然出现在全局范围的 mpfr 编码中,但实际上是从 mpreal 的范围内调用的。由于 mpreal 已将 srcptr 重新定义为函数,因此该定义是从 mpreal 执行 SRCPTR 时唯一使用的定义。 (SRCPTR 作为宏,没有作用域。)当从 mpreal 调用 mpfr 的函数时,这些函数在全局作用域内运行,因此在那里调用的 SRCPTR 宏将使用全局定义。