1

I'm trying to understand how the compiler handles this code. The two class methods both reference the enumeration before it is defined, but only one generates a compile error. I'm using 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
    };
};

In this case, the function Foo compiles fine under gcc 9.2, but Bar does not:

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) {

Why does gcc seem to accept the usage of the enum prior to definition in one instance but not another? I understand that the enum should be declared before these functions, but why does Foo compile without error?

1 Answer 1

0

Maybe you can see this as a lack of declaration of TestState by the time Bar(TestState) is declared. Actually this code can be simplified as below:

struct A {
    void f() {}   /// fine
    void g(B) {}  /// not fine

    struct B {};
};

int main() {
    return 0;
}

This code just can't compile as yours, since by the time g(B) is declared, the compiler needs to look up where the declaration of B is, which cannot be found.

That's when we need Forward Declaration. Add a forward declaration, and you may find compilation successful:

struct A {
    void f() {}  /// fine

    struct B;

    void g(B) {}  /// fine now

    struct B {};
};

int main() {
    return 0;
}

It's the same with your code. So add private: enum class TestState : bool; before the public in your code, and it'll compile.

Sign up to request clarification or add additional context in comments.

2 Comments

But this doesn't explain why Foo compiles successfully when it uses the enum in its definition. I understand the need for a forward declaration here. I'm still curious about why GCC compiles Foo without error.
@cbwoyak The declaration of Foo does not require TestState, while its definition requires. You may consider separate compilation, where most of time declaration included is in the top few lines of the implementation file. In this way you can easily understand that by the time sth is declared, its corresponding definition is not immediately needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.