【问题标题】:Use of scoped enum in a class prior to its definition在定义之前在类中使用作用域枚举
【发布时间】:2021-09-02 18:08:40
【问题描述】:

我试图了解编译器如何处理此代码。这两个类方法都在定义之前引用了枚举,但只有一个会产生编译错误。我正在使用 GCC 9.2:

class Test {
  public:
    Test() {}
    ~Test(){}

    //gcc seems to be happy with this...
    int Foo()
    {
      TestState v = TestState::Value1;
      if (v == TestState::Value1) {
        return 0;
      } else if (v == TestState::Value2) {
        return 1;
      }
    }

    // ... but it doesn't work when used as a parameter
    int Bar(TestState v)
    {
      if (v == TestState::Value1) {
        return 0;
      } else if (v == TestState::Value2) {
        return 1;
      }
    }
  private:
    enum class TestState:bool
    {
      Value1 = false,
      Value2 = true
    };
};

在这种情况下,函数 Foo 在 gcc 9.2 下编译得很好,但 Bar 没有:

enum.cpp:18:13: error: ‘TestState’ has not been declared
     int Bar(TestState v)
             ^
enum.cpp: In member function ‘int Test::Bar(int)’:
enum.cpp:20:13: error: no match for ‘operator==’ (operand types are ‘int’ and ‘Test::TestState’)
       if (v == TestState::Value1) {
             ^
enum.cpp:22:20: error: no match for ‘operator==’ (operand types are ‘int’ and ‘Test::TestState’)
       } else if (v == TestState::Value2) {

为什么 gcc 在一个实例中似乎接受在定义之前使用枚举,而在另一个实例中不接受?我知道枚举应该在这些函数之前声明,但是为什么Foo编译没有错误?

【问题讨论】:

    标签: c++11 enums compiler-errors


    【解决方案1】:

    也许您可以在声明 Bar(TestState) 时将其视为缺少 TestState 声明。其实这段代码可以简化如下:

    struct A {
        void f() {}   /// fine
        void g(B) {}  /// not fine
    
        struct B {};
    };
    
    int main() {
        return 0;
    }
    

    这段代码不能像你的那样编译,因为在声明g(B)时,编译器需要查找B的声明在哪里,找不到。

    那时我们需要Forward Declaration。添加一个前向声明,你可能会发现编译成功:

    struct A {
        void f() {}  /// fine
    
        struct B;
    
        void g(B) {}  /// fine now
    
        struct B {};
    };
    
    int main() {
        return 0;
    }
    

    您的代码也是如此。所以在你的代码中在public之前添加private: enum class TestState : bool;,它就会编译。

    【讨论】:

    • 但这并不能解释为什么 Foo 在其定义中使用枚举时编译成功。我理解这里需要提前声明。我还是很好奇为什么 GCC 编译 Foo 没有错误。
    • @cbwoyak Foo声明不需要TestState,而它的定义需要。您可以考虑单独编译,其中大部分时间声明包含在实现文件的前几行中。这样你就可以很容易的理解,当 sth 被声明的时候,它的对应定义并不是立即需要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    • 1970-01-01
    相关资源
    最近更新 更多