0

The following code works, but it is not very readable to have methods separated from each state of this state machine:

struct Base {
    virtual Base* next() = 0;
};

struct StateA : public Base {
    Base* next();
};

struct StateB : public Base {
    Base* next();
};

StateA stateA;
StateB stateB;

Base* StateA::next() {
    return &stateB;
}

Base* StateB::next() {
    return &stateA;
}

I would rather prefer to have this structure, unfortunately, I don't know if it is possible in C++ to foward declare stateA and stateB:

struct Base {
    virtual Base* next() = 0;
};

struct StateA : public Base {
    Base* next() { return &stateB; }
};

struct StateB : public Base {
    Base* next() { return &stateA; }
};

StateA stateA;
StateB stateB;

Is it possible to keep the implementation of StateX along with their declaration?

I have tried to trick the compiler with this, but as guessed, it doesn't build:

struct Base {
    virtual Base* next() = 0;
};

struct StateA;
struct StateB;

extern StateA *stateAptr;
extern StateB *stateBptr;

struct StateA : public Base {
    Base* next() { return stateBptr; }
};

struct StateB : public Base {
    Base* next() { return stateAptr; }
};

StateA stateA;
StateB stateB;
StateA *stateAptr = &stateA;
StateB *stateBptr = &stateB;
nowox
  • 25,978
  • 39
  • 143
  • 293
  • "it is not very readable to have methods separated from each state of this state machine". Q: Are you saying that you don't like a declaration in one place (e.g. a header file) and a definition in a separate place (e.g. .c or .cpp implementation files)? Q: What exactly are your questions about/problems with "extern"? Does this link help: https://stackoverflow.com/a/1433387/421195 – paulsm4 May 03 '23 at 20:07
  • I have a state machine with several states. Each state have several methods (entry, exit, stay). Having each implementation located in each State is convenient. Also these states can stay in a single cpp file since the interface is a global StateMachine that use all states. @paulsm4 does it answer your Q? – nowox May 03 '23 at 20:23

1 Answers1

1

The keyword extern is responsible for forward variable declarations. But it's can be used before their types are defined. You can split member function declarations and definitions.

struct Base {
    virtual Base* next() = 0;
};

struct StateA : public Base {
    Base* next();
};

struct StateB : public Base {
    Base* next();
};

StateB stateB;
StateA stateA;

Base* StateA::next() { return &stateB; }
Base* StateB::next() { return &stateA; }

Or update your trick for using Base* pointers.

struct Base {
    virtual Base* next() = 0;
};

extern Base *stateAptr;
extern Base *stateBptr;

struct StateA : public Base {
    Base* next() { return stateBptr; }
};

struct StateB : public Base {
    Base* next() { return stateAptr; }
};

StateA stateA;
StateB stateB;
Base *stateAptr = &stateA;
Base *stateBptr = &stateB;

But it does not improve readability in comparison with the first code, and conflicts with your sentence "it is not very readable".

273K
  • 29,503
  • 10
  • 41
  • 64