【问题标题】:gcc warning "does not declare anythinggcc 警告“没有声明任何东西
【发布时间】:2019-08-06 14:14:09
【问题描述】:

我正在通过将 typedef 转换为使用别名来将一些 C++ 代码更新为 C+11。给定以下 SCCE:

#include <iostream>
#include <linux/cn_proc.h>
/**
 * Legacy C structure
 */
struct sample {
  enum what {
    FOO,
    BAR
  } what;
};

void tdef( ) {
    typedef enum sample::what demo;
    demo a = sample::FOO;
    std::cout << a << std::endl;
}

void usingdemo( ) {
    using demo = enum sample::what;
    demo a = sample::BAR;
    std::cout << a
    << std::endl;
}

int main() {
    tdef();
    usingdemo();
}

我在使用 using 声明时收到警告:

warning: declaration ‘enum sample::what’ does not declare anything
     using demo = enum sample::what;
                               ^

虽然代码编译和执行都很好。编译器是g++ (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609 问题出在编译器上,还是在我身上?


感谢您的回复。关于 C 结构的 cmets:

  • “S”是 SCCE 很小,所以我发布了最小的结构 证明问题。我使用的实际结构是“struct proc_event” linux/cn_proc.h

  • 我只是将它包含在没有“extern C”的情况下 它工作正常。

【问题讨论】:

  • 如果你删除enum会有什么变化吗?
  • @melpomene - 是的,它会 - 一个不同的错误,而不是警告。
  • @melpomene 是的。它拒绝说what 不是结构的代码。 FWIW clang 和 icc 不会抱怨 OP 代码中的任何内容。 gcc 中的诊断可能不正确。
  • @luk32 VC++ 也没有 /W4
  • 您是否尝试过`using demo = typename sample::what;'?毕竟是嵌套类型。

标签: c++ c++11 gcc


【解决方案1】:

问题出在编译器上吗?

这是一个编译器错误。它似乎已经被报道过:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66159。当在 using 声明中使用详细的名称说明符时,该问题会重现。在这种情况下,您需要使用详细的名称说明符以避免与具有相同名称的成员产生歧义。

解决方法:改用typedef 声明:

typedef enum sample::what demo;

【讨论】:

    【解决方案2】:

    问题是您同时创建了一个类型sample::what 和一个成员sample::what。编译器应该并且显然确实解决了这个问题,并且警告是良性的并且显然是错误的。

    问题消失了:

    struct sample {
      enum what {
        FOO,
        BAR
      } what_instance;  //  << Different identifier here
    };
    

    和:

    using demo = sample::what;
    

    在任何情况下,使用相同名称的类型标识符和实例标识符都是一个坏主意,原因有很多。它使人类感到困惑,在这种情况下,编译器也是如此。也许编译器试图告诉你一些事情;-)

    【讨论】:

    • 是的,但 OP 没有声明该枚举并且可能无法更改它:elixir.bootlin.com/linux/latest/source/include/uapi/linux/…。它似乎是 Linux 头文件的一部分。
    • @DanielLangr,这显然是 C 代码,这是 C++,所以如果结构引用相同的东西,它应该有一个 extern "C" 声明。这也不能解决问题。你对 Linux 的编码标准有什么看法!?
    • 没什么,但我认为这是一种非常糟糕的编码实践(将枚举/结构/类命名为与其实例相同)。令我惊讶的是它在 Linux 标头中。
    • @Clifford 我认为结构定义不需要extern "C" - 函数和全局变量需要它。
    • @Clifford 正确。但这与是否需要extern "C" 无关。
    【解决方案3】:

    您可以简单地将演示类型定义为 int,因为 enum 可以转换为临时 int

    void usingdemo( ) {
      using demo = int;
      ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多