为什么 gcc 会误解这个宏?

问题描述

我发现 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 宏将使用全局定义。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...