【问题标题】:Is it legal to re-declare a member class after defining it?定义成员类后重新声明是否合法?
【发布时间】:2025-12-17 02:10:02
【问题描述】:

我在编译 boost.bimap 库时遇到问题。我的测试程序是一个空白的主函数,只有一个包含指令(如#include <boost/bimap.hpp>)。 经过一番调查,我发现预处理器从头文件中做了一些有趣的构造,例如:

struct A { struct B{}; struct B; };

我不知道这是否正确,但 gcc 接受它,而 clang 和 icc 不接受。谁是对的,我该怎么做才能用 bimap 库编译程序?不幸的是,在这种情况下我不能使用 gcc。

【问题讨论】:

  • 在我看来,一切都像是你在其他地方遇到了错误,这是从预处理器的角度来看的结果。
  • 这个问题与Boost.Bimap无关。仅仅因为您在代码的其他部分使用它并不意味着它与此相关。
  • 您遇到的错误究竟是什么? (你为什么不一开始就告诉我们呢?)
  • 嵌套类 BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER 的无效重新声明我收到此错误
  • 这不是完全您遇到的错误,因为您遗漏了[-Werror,-Wredeclared-class-member] 这是重要部分的部分。这表明您正在使用 -Werror,并且可以通过不这样做来解决问题。

标签: c++ c-preprocessor bimap boost-bimap


【解决方案1】:

struct B{};定义了一个嵌套类,那么struct B;就是对同一个嵌套类的重新声明。

GCC 接受代码是错误的 (bug report),因为标准在 [class.mem] 中说:

一个成员在member-specification中不能被声明两次,除非可以声明一个嵌套类或成员类模板,然后再定义,

在您的情况下,嵌套类被定义然后声明,这是不允许的,因此 Clang 和 ICC 是正确的给出诊断。但是,当我测试它时,它们只会给出警告,而不是错误,所以也许你正在使用-Werror,在这种情况下停止这样做并且代码应该编译。

Boost.Bimap 代码中的问题是known bug

【讨论】:

  • 我从我的问题 here 链接到这个答案