Topic: forward declarations and scoping


Author: Steve Hickman <shickman@sprintcorp.com>
Date: 1998/05/04
Raw View

In an attempt to clean up the global namespace on a project I am working
on, I decided recently to begin creating "packages" of related classes.
Since namespaces are not yet supported by the compiler I am using, I use
structs instead. This attempt is failing for a very simple reason: The
forward declarations that
I used do not compile now that they are "scoped". (See the example
below).

I don't know if the same thing will happen with namespaces, but if it
does, I contend that this is a language flaw. Forward declarations are
very useful for eliminating circular dependencies between classes. If
scoped forward declarations are impossible, then we are forced to choose
between scoping and forward declarations under certain circumstances.

Any comments?

/* --------------------- Old way ------------------------ */
/* StateMachine.h */
#include "Event.h"

class StateContext
{
 DCL_ABS_CANONICAL_FORM(StateContext)
 public:
  typedef StdNullLock Lock;
  typedef string ID;
 protected:
  ID id;
  State *curState;
  Lock cLock;

 public:
  StateContext(const StateContext::ID &uid);

  void        setID(const string &n){id = n; }
  const StateContext::ID &getID() const { return id; }
        StateID  getStateID() const; //  { return curState->id(); }
  State *setNextState(State *newState); //
  State *getState() const; //  { return curState; }

  /* Eactly how an instance retrieves the action to perform
     will depend of the derived class. This allows some
     derived classes to have the actions associated directly
     with the class, while it allows others to get the action
     from an indirectly associated instance
     */
  virtual StateAction *getAction(ActionID aid) const = 0;
};
DCL_STREAM_OUT(StateContext)


class State
{
 DCL_CANONICAL_FORM(State)

 public:
  static char * STATE_TRANSITION_RULE;
  static char * TRANSITION;
  static StateID INITIAL;

//  enum LineType {  WAVEFORM =2,
//     STATE_TRANSITION_RULE  };

 private:
  StateID myID;
  TransRules transRules;
 public:
  State(StateID id):myID(id) {};

  StateID id() const;
  void addTransRule(Event::ID eid, StateTransitionRule str);
  void addTransRule (istream *input, StateTable *st);
  void addTransRules(istream *input, StateTable *st);
//  void fill         (istream *input);
  CmdStatus transition(Event *ev, StateContext *sc);
};
DCL_STREAM_OUT(State)

/* Event.h */


//class StateMachine;
//class StateMachine::State;
//class StateMachine::Context;

//template <class KeyType>
class Event
{
  DCL_CANONICAL_FORM(Event)

  public:
  typedef int ID;

  enum CATEGORY { INVALID_CATEGORY = -1,
       REQUEST,
       RETURN_RESULT,
       RETURN_ERROR,
       REJECT,
       UNIDIRECTIONAL };

  enum { INVALID_ID = -1};

 protected:
//  GenericLocalObjPtr src;
  void *src;

  CATEGORY cat;
  ID family;
  ID eid;
  Priority prio;
  string otherInfo;

 public:
  Event(// const GenericLocalObjPtr &optr,
             const CATEGORY &t,
      const ID &fam,
      const ID &id,
      Priority p = NORMAL_PRIO,
             void *ptr = NULL);

  void initMembers(// const GenericLocalObjPtr &,
                   const CATEGORY &t,
     const ID &fam,
     const ID &id,
     Priority p = NORMAL_PRIO,
                   void *ptr = NULL);

  /* GenericLocalObjPtr stores void * ptr reference */
//  void set_src(void * s) { src.setObj(s); }
//  void * get_src() const { return src.getObj(); }

  GET_SETP(void,     src);
  GET_SET(CATEGORY,      cat)
  GET_SET(ID,        family)
  GET_SET(ID,        eid)
  GET_SET(Priority,       prio)
  GET_SET(string,         otherInfo)
  void set_otherInfo(BYTE *data, int len)
    { otherInfo.assign((char *)data,len); }

//  virtual CmdStatus apply(State *state, StateContext *sc);


};


/* ---------------- New Way - doesn't work --------------- */
#include "Event.h"

struct StateMachine
{
  class State
  {
    DCL_CANONICAL_FORM(State)

  public:
    static char * STATE_TRANSITION_RULE;
    static char * TRANSITION;
    static ID INITIAL;

    //  enum LineType {  WAVEFORM =2,
    //     STATE_TRANSITION_RULE  };

  private:
    ID myID;
    TransRules transRules;
  public:
    State(ID id):myID(id) {};

    ID id() const;
    void addTransRule(Event::ID eid, TransitionRule str);
    void addTransRule (istream *input, Table *st);
    void addTransRules(istream *input, Table *st);
    //  void fill         (istream *input);
    CmdStatus transition(Event *ev, Context *sc);
  };

  class Context
  {
    DCL_ABS_CANONICAL_FORM(Context)
      public:
    typedef StdNullLock Lock;
    typedef string ID;
  protected:
    ID id;
    State *curState;
    Lock cLock;
    Actions *relevantActions;

  public:
    Context(const Context::ID &uid);

    void        setID(const string &n){id = n; }
    const Context::ID &getID() const { return id; }
    ID  getStateID() const; //  { return curState->id(); }
    State *setNextState(State *newState); //
    State *getState() const; //  { return curState; }

    GET_SETP(Actions, relevantActions);

    /* Eactly how an instance retrieves the action to perform
       will depend of the derived class. This allows some
       derived classes to have the actions associated directly
       with the class, while it allows others to get the action
       from an indirectly associated instance
       */
    virtual Action *getAction(ActionID aid) const
      { return (*relevantActions)[aid]; }

  };



}; /* end StateMachine */

/* Event.h */
//class StateMachine;
class StateMachine::State;
class StateMachine::Context;

//template <class KeyType>
class Event
{
  DCL_CANONICAL_FORM(Event)

  public:
  typedef int ID;

  enum CATEGORY { INVALID_CATEGORY = -1,
       REQUEST,
       RETURN_RESULT,
       RETURN_ERROR,
       REJECT,
       UNIDIRECTIONAL };

  enum { INVALID_ID = -1};

 protected:
//  GenericLocalObjPtr src;
  void *src;

  CATEGORY cat;
  ID family;
  ID eid;
  Priority prio;
  string otherInfo;

 public:
  Event(// const GenericLocalObjPtr &optr,
             const CATEGORY &t,
      const ID &fam,
      const ID &id,
      Priority p = NORMAL_PRIO,
             void *ptr = NULL);

  void initMembers(// const GenericLocalObjPtr &,
                   const CATEGORY &t,
     const ID &fam,
     const ID &id,
     Priority p = NORMAL_PRIO,
                   void *ptr = NULL);

  /* GenericLocalObjPtr stores void * ptr reference */
//  void set_src(void * s) { src.setObj(s); }
//  void * get_src() const { return src.getObj(); }

  GET_SETP(void,     src);
  GET_SET(CATEGORY,      cat)
  GET_SET(ID,        family)
  GET_SET(ID,        eid)
  GET_SET(Priority,       prio)
  GET_SET(string,         otherInfo)
  void set_otherInfo(BYTE *data, int len)
    { otherInfo.assign((char *)data,len); }

//  virtual CmdStatus apply(StateMachine::State *state,
StateMachine::Context *sc);


};

begin:          vcard
fn:             Steve Hickman
n:              Hickman;Steve
org:            Sprint
adr:            7101 College;;10th Floor;Overland Park;Kansas;66210;USA
email;internet: shickman@sprintcorp.com
title:          Software Architect
tel;work:       913-534-6668
tel;fax:        913-534-6520
x-mozilla-cpt:  ;0
x-mozilla-html: TRUE
version:        2.1
end:            vcard


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]