How to make every derived class to return a different int

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Stefano Sabatini

    How to make every derived class to return a different int

    Hi all,

    I'm facing this design problem.

    I have a table which defines the behaviour of an Object in a given
    state according to the type of event it is receiving.

    So for each couple event,state I want I set in the table a different
    handler.

    My trivial implementation make use of defines (but I could have used
    an enum as well).

    So I have:
    #define EVT_FOO 0
    #define EVT_BAR 1
    ....
    #define EVT_FOOBAR N

    Then I define for each event a virtual GetType() which returns the
    event type.

    This is ugly and awkward, since everytime I add an event I have to
    update the enum/list of defines, while I would like to be able to
    automatically get a different integer for every derived class of
    Event.

    Mayeb I could get this result with some kind of run-time registration
    mechanism.

    I think this problem should be quite common, so I thought maybe
    someone can suggest a better design than that which requires the
    enum/defines list.

    Regards.
  • Kai-Uwe Bux

    #2
    Re: How to make every derived class to return a different int

    Stefano Sabatini wrote:
    Hi all,
    >
    I'm facing this design problem.
    >
    I have a table which defines the behaviour of an Object in a given
    state according to the type of event it is receiving.
    >
    So for each couple event,state I want I set in the table a different
    handler.
    >
    My trivial implementation make use of defines (but I could have used
    an enum as well).
    >
    So I have:
    #define EVT_FOO 0
    #define EVT_BAR 1
    ...
    #define EVT_FOOBAR N
    >
    Then I define for each event a virtual GetType() which returns the
    event type.
    >
    This is ugly and awkward, since everytime I add an event I have to
    update the enum/list of defines, while I would like to be able to
    automatically get a different integer for every derived class of
    Event.
    >
    Mayeb I could get this result with some kind of run-time registration
    mechanism.
    What about something like this:


    unsigned int
    count ( void ) {
    static unsigned int c = 0;
    return ( c++ );
    }

    struct reg_base {

    virtual
    unsigned int get_id ( void ) = 0;

    };

    template < typename D >
    class reg : public reg_base {

    static unsigned int const id;

    public:

    unsigned int get_id ( void ) {
    return ( id );
    }

    };

    template < typename D >
    unsigned int const reg<D>::id = count();


    struct X : public reg<X{};
    struct Y : public reg<Y{};

    #include <iostream>

    int main ( void ) {
    X x;
    Y y1;
    Y y2;
    reg_base * p = new Y ();

    std::cout << "X " << x.get_id() << '\n';
    std::cout << "Y " << y1.get_id() << '\n';
    std::cout << "Y " << y2.get_id() << '\n';
    std::cout << "Y " << p->get_id() << '\n';
    }

    You could also add a static method that yields the id of a type.

    I think this problem should be quite common, so I thought maybe
    someone can suggest a better design than that which requires the
    enum/defines list.

    Best

    Kai-Uwe Bux

    Comment

    • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

      #3
      Re: How to make every derived class to return a different int

      On 2008-09-22 16:14, Stefano Sabatini wrote:
      Hi all,
      >
      I'm facing this design problem.
      >
      I have a table which defines the behaviour of an Object in a given
      state according to the type of event it is receiving.
      >
      So for each couple event,state I want I set in the table a different
      handler.
      >
      My trivial implementation make use of defines (but I could have used
      an enum as well).
      >
      So I have:
      #define EVT_FOO 0
      #define EVT_BAR 1
      ...
      #define EVT_FOOBAR N
      >
      Then I define for each event a virtual GetType() which returns the
      event type.
      >
      This is ugly and awkward, since everytime I add an event I have to
      update the enum/list of defines, while I would like to be able to
      automatically get a different integer for every derived class of
      Event.
      >
      Mayeb I could get this result with some kind of run-time registration
      mechanism.
      You could put a const int in the base-class and set it to the correct
      value in the constructor of each event class.
      I think this problem should be quite common, so I thought maybe
      someone can suggest a better design than that which requires the
      enum/defines list.
      It seems like you have a problem with your design. If you want to use
      the number to distinguish the different events and based on that perform
      different actions perhaps you should consider overloading some function
      for the different event types instead.

      --
      Erik Wikström

      Comment

      • puzzlecracker

        #4
        Re: How to make every derived class to return a different int

        unsigned int
        count ( void ) {
          static unsigned int c = 0;
          return ( c++ );
        >
        }
        >
        struct reg_base {
        >
          virtual
          unsigned int get_id ( void ) = 0;
        >
        };
        >
        template < typename D >
        class reg : public reg_base {
        >
          static unsigned int const id;
        >
        public:
        >
          unsigned int get_id ( void ) {
            return ( id );
          }
        >
        };
        >
        template < typename D >
        unsigned int const reg<D>::id = count();
        >
        struct X : public reg<X{};
        struct Y : public reg<Y{};
        >
        #include <iostream>
        >
        int main ( void ) {
          X x;
          Y y1;
          Y y2;
          reg_base * p = new Y ();
        >
          std::cout << "X " << x.get_id() << '\n';
          std::cout << "Y " << y1.get_id() << '\n';
          std::cout << "Y " << y2.get_id() << '\n';
          std::cout << "Y " << p->get_id() << '\n';
        >
        }
        I think it's better to eliminate count function altogether and put the
        count functionality into class/struct such as, in your case, reg_base.
        struct counter{

        static unsigned int count getId(return id++;)

        private:
        static unsigned int id;

        };
        unsigned int counter::id=0;


        Or some cleaner variation of that. I don't like member-less function
        in the code. At the very least, we ought to namespace it if we're to
        have this function, given that it's short to use and easier to code
        than an alternative I've just mentioned.

        Comment

        • Hendrik Schober

          #5
          Re: How to make every derived class to return a different int

          Stefano Sabatini wrote:
          Hi all,
          >
          I'm facing this design problem.
          >
          I have a table which defines the behaviour of an Object in a given
          state according to the type of event it is receiving.
          >
          So for each couple event,state I want I set in the table a different
          handler.
          >
          My trivial implementation make use of defines (but I could have used
          an enum as well).
          >
          So I have:
          #define EVT_FOO 0
          #define EVT_BAR 1
          ....
          #define EVT_FOOBAR N
          >
          Then I define for each event a virtual GetType() which returns the
          event type.
          What are you doing with these event/state couples?
          Could it be that what you need is multi-methods?
          Have you looked into patterns? I suspect that there are much
          better ways to achieve whatever you're trying to do.
          This is ugly and awkward, since everytime I add an event I have to
          update the enum/list of defines, while I would like to be able to
          automatically get a different integer for every derived class of
          Event.
          >
          Mayeb I could get this result with some kind of run-time registration
          mechanism.
          It seems a compile-time problem, but I don't see a way to do
          this at compile-time except by using vendor-specific compiler
          extensions. (ISTR VC having some macro that expands to different
          integers for each usage.)
          I think this problem should be quite common, so I thought maybe
          someone can suggest a better design than that which requires the
          enum/defines list.
          I think so, too.
          What are you trying to do with your event/state couples?

          Schobi

          Comment

          • Kai-Uwe Bux

            #6
            Re: How to make every derived class to return a different int

            puzzlecracker wrote:
            >
            >unsigned int
            >count ( void ) {
            >static unsigned int c = 0;
            >return ( c++ );
            >>
            >}
            >>
            >struct reg_base {
            >>
            >virtual
            >unsigned int get_id ( void ) = 0;
            >>
            >};
            >>
            >template < typename D >
            >class reg : public reg_base {
            >>
            >static unsigned int const id;
            >>
            >public:
            >>
            >unsigned int get_id ( void ) {
            >return ( id );
            >}
            >>
            >};
            >>
            >template < typename D >
            >unsigned int const reg<D>::id = count();
            >>
            >struct X : public reg<X{};
            >struct Y : public reg<Y{};
            >>
            >#include <iostream>
            >>
            >int main ( void ) {
            >X x;
            >Y y1;
            >Y y2;
            >reg_base * p = new Y ();
            >>
            >std::cout << "X " << x.get_id() << '\n';
            >std::cout << "Y " << y1.get_id() << '\n';
            >std::cout << "Y " << y2.get_id() << '\n';
            >std::cout << "Y " << p->get_id() << '\n';
            >>
            >}
            >
            I think it's better to eliminate count function altogether and put the
            count functionality into class/struct such as, in your case, reg_base.
            struct counter{
            >
            static unsigned int count getId(return id++;)
            >
            private:
            static unsigned int id;
            >
            };
            unsigned int counter::id=0;
            >
            >
            Or some cleaner variation of that. I don't like member-less function
            in the code. At the very least, we ought to namespace it if we're to
            have this function, given that it's short to use and easier to code
            than an alternative I've just mentioned.
            Yup. Also, get_id() wasn't const. Here is a cleaner version:

            class reg_base {
            protected:

            static
            unsigned int
            count ( void ) {
            static unsigned int c = 0;
            return ( c++ );
            }

            public:

            virtual
            unsigned int get_id ( void ) const = 0;

            virtual
            ~reg_base ( void ) {}

            };

            template < typename D >
            class reg : public reg_base {

            static unsigned int const the_id;

            public:

            unsigned int get_id ( void ) const {
            return ( the_id );
            }

            static
            unsigned int id ( void ) {
            return ( the_id );
            }

            virtual
            ~reg ( void ) {}

            };

            template < typename D >
            unsigned int const reg<D>::the_id = reg<D>::reg_bas e::count();


            struct X : public reg<X{};
            struct Y : public reg<Y{};

            #include <iostream>

            int main ( void ) {
            X x;
            Y y1;
            Y y2;
            reg_base * px = new X ();
            reg_base * py = new Y ();

            std::cout << "X " << x.get_id() << '\n';
            std::cout << "Y " << y1.get_id() << '\n';
            std::cout << "Y " << y2.get_id() << '\n';

            std::cout << "X " << px->get_id() << '\n';
            std::cout << "Y " << py->get_id() << '\n';

            std::cout << "X " << X::id() << '\n';
            std::cout << "Y " << Y::id() << '\n';

            delete ( px );
            delete ( py );
            }


            Best

            Kai-Uwe Bux

            Comment

            • Stefano Sabatini

              #7
              Re: How to make every derived class to return a different int

              On 2008-09-22, Erik Wikström <Erik-wikstrom@telia. comwrote:
              On 2008-09-22 16:14, Stefano Sabatini wrote:
              >Hi all,
              >>
              >I'm facing this design problem.
              >>
              >I have a table which defines the behaviour of an Object in a given
              >state according to the type of event it is receiving.
              >>
              >So for each couple event,state I want I set in the table a different
              >handler.
              >>
              >My trivial implementation make use of defines (but I could have used
              >an enum as well).
              >>
              >So I have:
              >#define EVT_FOO 0
              >#define EVT_BAR 1
              >...
              >#define EVT_FOOBAR N
              >>
              >Then I define for each event a virtual GetType() which returns the
              >event type.
              >>
              >This is ugly and awkward, since everytime I add an event I have to
              >update the enum/list of defines, while I would like to be able to
              >automaticall y get a different integer for every derived class of
              >Event.
              >>
              >Maybe I could get this result with some kind of run-time registration
              >mechanism.
              >
              You could put a const int in the base-class and set it to the correct
              value in the constructor of each event class.
              Yes I already do that, I have a m_Type const int field in the Event
              object and a GetType() which returns this type, every GetType() is
              redefined for each object (for example for each Event object), so that
              every one returns a different value. The problem is that I have to
              rely on the enum/defines already defined, while I would like to be
              able to add a new event type without the need to redefine the
              enums/defines.
              >I think this problem should be quite common, so I thought maybe
              >someone can suggest a better design than that which requires the
              >enum/defines list.
              >
              It seems like you have a problem with your design. If you want to use
              the number to distinguish the different events and based on that perform
              different actions perhaps you should consider overloading some function
              for the different event types instead.
              Well in this case I need to redefine a different integer for every
              object type, this because that index is used to access a table.
              This table defines an handler to be called for each state/event
              couple, that is for each event arrived I want to perform a different
              action based on the state of the object.

              Thanks for your help.

              (I'll look at the other comments too soon).

              Comment

              • Stefano Sabatini

                #8
                Re: How to make every derived class to return a different int

                On 2008-09-22, Hendrik Schober <spamtrap@gmx.d ewrote:
                Stefano Sabatini wrote:
                >Hi all,
                >>
                >I'm facing this design problem.
                >>
                >I have a table which defines the behaviour of an Object in a given
                >state according to the type of event it is receiving.
                >>
                >So for each couple event,state I want I set in the table a different
                >handler.
                >>
                >My trivial implementation make use of defines (but I could have used
                >an enum as well).
                >>
                >So I have:
                >#define EVT_FOO 0
                >#define EVT_BAR 1
                >....
                >#define EVT_FOOBAR N
                >>
                >Then I define for each event a virtual GetType() which returns the
                >event type.
                >
                What are you doing with these event/state couples?
                Could it be that what you need is multi-methods?
                Have you looked into patterns? I suspect that there are much
                better ways to achieve whatever you're trying to do.
                Mmmh... do you mean something like this:

                ?

                Yes I should know better patterns...
                >This is ugly and awkward, since everytime I add an event I have to
                >update the enum/list of defines, while I would like to be able to
                >automaticall y get a different integer for every derived class of
                >Event.
                >>
                >Mayeb I could get this result with some kind of run-time registration
                >mechanism.
                >
                It seems a compile-time problem, but I don't see a way to do
                this at compile-time except by using vendor-specific compiler
                extensions. (ISTR VC having some macro that expands to different
                integers for each usage.)
                >
                >I think this problem should be quite common, so I thought maybe
                >someone can suggest a better design than that which requires the
                >enum/defines list.
                >
                I think so, too.
                What are you trying to do with your event/state couples?
                I have a table which defines for each incoming event/state the handler
                to call. So I need an index for each event subtype, and I need the
                number of the the events to be known when I build the table in the
                constructor of the objects which defines and use that table.

                Thanks for your help, regards.

                Comment

                • Stefano Sabatini

                  #9
                  Re: How to make every derived class to return a different int

                  On 2008-09-22, Kai-Uwe Bux <jkherciueh@gmx .netwrote:
                  puzzlecracker wrote:
                  [...]
                  >I think it's better to eliminate count function altogether and put the
                  >count functionality into class/struct such as, in your case, reg_base.
                  >struct counter{
                  >>
                  > static unsigned int count getId(return id++;)
                  >>
                  > private:
                  > static unsigned int id;
                  >>
                  > };
                  >unsigned int counter::id=0;
                  >>
                  >>
                  >Or some cleaner variation of that. I don't like member-less function
                  >in the code. At the very least, we ought to namespace it if we're to
                  >have this function, given that it's short to use and easier to code
                  >than an alternative I've just mentioned.
                  >
                  Yup. Also, get_id() wasn't const. Here is a cleaner version:
                  >
                  class reg_base {
                  protected:
                  >
                  static
                  unsigned int
                  count ( void ) {
                  static unsigned int c = 0;
                  return ( c++ );
                  }
                  >
                  public:
                  >
                  virtual
                  unsigned int get_id ( void ) const = 0;
                  >
                  virtual
                  ~reg_base ( void ) {}
                  >
                  };
                  >
                  template < typename D >
                  class reg : public reg_base {
                  >
                  static unsigned int const the_id;
                  >
                  public:
                  >
                  unsigned int get_id ( void ) const {
                  return ( the_id );
                  }
                  >
                  static
                  unsigned int id ( void ) {
                  return ( the_id );
                  }
                  >
                  virtual
                  ~reg ( void ) {}
                  >
                  };
                  >
                  template < typename D >
                  unsigned int const reg<D>::the_id = reg<D>::reg_bas e::count();
                  >
                  >
                  struct X : public reg<X{};
                  struct Y : public reg<Y{};
                  >
                  #include <iostream>
                  >
                  int main ( void ) {
                  X x;
                  Y y1;
                  Y y2;
                  reg_base * px = new X ();
                  reg_base * py = new Y ();
                  >
                  std::cout << "X " << x.get_id() << '\n';
                  std::cout << "Y " << y1.get_id() << '\n';
                  std::cout << "Y " << y2.get_id() << '\n';
                  >
                  std::cout << "X " << px->get_id() << '\n';
                  std::cout << "Y " << py->get_id() << '\n';
                  >
                  std::cout << "X " << X::id() << '\n';
                  std::cout << "Y " << Y::id() << '\n';
                  >
                  delete ( px );
                  delete ( py );
                  }
                  Yes, I tried it and it is indeed what I need. Only what I also need
                  would be a static method which returns the total number of objects
                  already registered.

                  But what I need most now is a crash course on templates ;-).

                  Thanks so much for all the help, you rock guys!!!

                  Comment

                  • Kai-Uwe Bux

                    #10
                    Re: How to make every derived class to return a different int

                    Stefano Sabatini wrote:
                    [snip]
                    Yes, I tried it and it is indeed what I need. Only what I also need
                    would be a static method which returns the total number of objects
                    already registered.
                    Objects or classes?

                    Assuming classes, this poses an interesting problem. Here are two attempts:

                    a)

                    class reg_base {
                    protected:

                    static
                    unsigned int &
                    the_count ( void ) {
                    static unsigned int c = 0;
                    return ( c );
                    }

                    static
                    unsigned int count ( void ) {
                    return ( the_count() ++ );
                    }

                    public:

                    static
                    unsigned int num_classes ( void ) {
                    return ( the_count() );
                    }

                    virtual
                    unsigned int get_id ( void ) const = 0;

                    virtual
                    ~reg_base ( void ) {}

                    };

                    template < typename D >
                    class reg : public reg_base {

                    static unsigned int const the_id;

                    public:

                    unsigned int get_id ( void ) const {
                    return ( the_id );
                    }

                    static
                    unsigned int id ( void ) {
                    return ( the_id );
                    }

                    virtual
                    ~reg ( void ) {}

                    };

                    template < typename D >
                    unsigned int const reg<D>::the_id = reg<D>::reg_bas e::count();


                    struct X : public reg<X{};
                    struct Y : public reg<Y{};
                    struct Z : public reg<Z{};

                    #include <iostream>

                    int main ( void ) {
                    std::cout << "Classes: " << reg_base::num_c lasses() << '\n';

                    X x;
                    Y y1;
                    Y y2;
                    reg_base * px = new X ();
                    reg_base * py = new Y ();

                    std::cout << "X " << x.get_id() << '\n';
                    std::cout << "Y " << y1.get_id() << '\n';
                    std::cout << "Y " << y2.get_id() << '\n';

                    std::cout << "X " << px->get_id() << '\n';
                    std::cout << "Y " << py->get_id() << '\n';

                    std::cout << "X " << X::id() << '\n';
                    std::cout << "Y " << Y::id() << '\n';

                    delete ( px );
                    delete ( py );
                    }


                    This one does not count the class Z. Honestly, I don't know the reason.


                    b)

                    class reg_base {
                    protected:

                    static
                    unsigned int &
                    the_count ( void ) {
                    static unsigned int c = 0;
                    return ( c );
                    }

                    static
                    unsigned int count ( void ) {
                    return ( the_count() ++ );
                    }

                    public:

                    static
                    unsigned int num_classes ( void ) {
                    return ( the_count() );
                    }

                    virtual
                    unsigned int get_id ( void ) const = 0;

                    virtual
                    ~reg_base ( void ) {}

                    };

                    template < typename D >
                    class reg : public reg_base {

                    static
                    unsigned int & the_id ( void ) {
                    static unsigned int dummy = 0;
                    return ( dummy );
                    }

                    struct do_register {

                    do_register ( void ) {
                    the_id() = reg<D>::reg_bas e::count();
                    }

                    };

                    public:

                    reg ( void ) {
                    static do_register dummy;
                    }

                    unsigned int get_id ( void ) const {
                    return ( the_id() );
                    }

                    static
                    unsigned int id ( void ) {
                    return ( the_id() );
                    }

                    virtual
                    ~reg ( void ) {}

                    };


                    struct X : public reg<X{};
                    struct Y : public reg<Y{};
                    struct Z : public reg<Z{};

                    #include <iostream>

                    int main ( void ) {
                    std::cout << "Classes: " << reg_base::num_c lasses() << '\n';
                    X x;
                    std::cout << "Classes: " << reg_base::num_c lasses() << '\n';
                    Y y1;
                    Y y2;
                    std::cout << "Classes: " << reg_base::num_c lasses() << '\n';
                    Z z;
                    std::cout << "Classes: " << reg_base::num_c lasses() << '\n';
                    reg_base * px = new X ();
                    reg_base * py = new Y ();

                    std::cout << "X " << x.get_id() << '\n';
                    std::cout << "Y " << y1.get_id() << '\n';
                    std::cout << "Y " << y2.get_id() << '\n';

                    std::cout << "X " << px->get_id() << '\n';
                    std::cout << "Y " << py->get_id() << '\n';

                    std::cout << "X " << X::id() << '\n';
                    std::cout << "Y " << Y::id() << '\n';

                    delete ( px );
                    delete ( py );
                    std::cout << "Classes: " << reg_base::num_c lasses() << '\n';
                    }

                    This one counts each class, once the first object of that class has been
                    constructed.



                    I don't know, which semantics you actually need.



                    Best

                    Kai-Uwe Bux

                    Comment

                    • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

                      #11
                      Re: How to make every derived class to return a different int

                      On 2008-09-23 16:51, Stefano Sabatini wrote:
                      On 2008-09-22, Erik Wikström <Erik-wikstrom@telia. comwrote:
                      >On 2008-09-22 16:14, Stefano Sabatini wrote:
                      >>I think this problem should be quite common, so I thought maybe
                      >>someone can suggest a better design than that which requires the
                      >>enum/defines list.
                      >>
                      >It seems like you have a problem with your design. If you want to use
                      >the number to distinguish the different events and based on that perform
                      >different actions perhaps you should consider overloading some function
                      >for the different event types instead.
                      >
                      Well in this case I need to redefine a different integer for every
                      object type, this because that index is used to access a table.
                      This table defines an handler to be called for each state/event
                      couple, that is for each event arrived I want to perform a different
                      action based on the state of the object.
                      I seems I was not clear enough about what I meant, so perhaps an example
                      will do instead:

                      #include <iostream>

                      // Classes that represents the different events
                      struct Event { };
                      struct FooEvent : public Event { };
                      struct BarEvent : public Event { };


                      // Functions to handle events in state A
                      void stateA(const Event& e)
                      {
                      std::cout << "Generic event handler when in state A\n";
                      }

                      void stateA(const FooEvent& e)
                      {
                      std::cout << "Handler for Foo events when in state A\n";
                      }


                      int main()
                      {
                      FooEvent foo;
                      BarEvent bar;

                      stateA(foo);
                      stateA(bar);

                      return 0;
                      }

                      Using this scheme it is easy to add new events and you only have to
                      update the code for those states which can handle the events (by
                      overloading the event-handler for the new event).

                      --
                      Erik Wikström

                      Comment

                      • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

                        #12
                        Re: How to make every derived class to return a different int

                        On 2008-09-23 19:40, Erik Wikström wrote:
                        On 2008-09-23 16:51, Stefano Sabatini wrote:
                        >On 2008-09-22, Erik Wikström <Erik-wikstrom@telia. comwrote:
                        >>On 2008-09-22 16:14, Stefano Sabatini wrote:
                        >
                        >>>I think this problem should be quite common, so I thought maybe
                        >>>someone can suggest a better design than that which requires the
                        >>>enum/defines list.
                        >>>
                        >>It seems like you have a problem with your design. If you want to use
                        >>the number to distinguish the different events and based on that perform
                        >>different actions perhaps you should consider overloading some function
                        >>for the different event types instead.
                        >>
                        >Well in this case I need to redefine a different integer for every
                        >object type, this because that index is used to access a table.
                        >This table defines an handler to be called for each state/event
                        >couple, that is for each event arrived I want to perform a different
                        >action based on the state of the object.
                        >
                        I seems I was not clear enough about what I meant, so perhaps an example
                        will do instead:
                        >
                        #include <iostream>
                        >
                        // Classes that represents the different events
                        struct Event { };
                        struct FooEvent : public Event { };
                        struct BarEvent : public Event { };
                        >
                        >
                        // Functions to handle events in state A
                        void stateA(const Event& e)
                        {
                        std::cout << "Generic event handler when in state A\n";
                        }
                        >
                        void stateA(const FooEvent& e)
                        {
                        std::cout << "Handler for Foo events when in state A\n";
                        }
                        >
                        >
                        int main()
                        {
                        FooEvent foo;
                        BarEvent bar;
                        >
                        stateA(foo);
                        stateA(bar);
                        >
                        return 0;
                        }
                        >
                        Using this scheme it is easy to add new events and you only have to
                        update the code for those states which can handle the events (by
                        overloading the event-handler for the new event).
                        I realised that you might want to be able to somehow store the state,
                        and I can see two ways of doing that. Either you can use create objects
                        for the states and overload the event handler function for both state
                        and event:

                        struct Event {};
                        struct FooEvent : public Event {};

                        struct State {};
                        struct BarState : public State {};


                        void eventHandler(co nst BarState& s, const Event& e)
                        {
                        // General event handler for state Bar
                        }

                        void eventHandler(co nst BarState& s, const FooEvent& e)
                        {
                        // Foo event handler for state Bar
                        }

                        The second alternative (which I think might be a bit more elegant) is to
                        make the event handlers member-functions of state-objects:


                        struct Event {};
                        struct FooEvent : public Event {};

                        struct State {};

                        struct BarState : public State
                        {
                        void handleEvent(con st FooEvent& e)
                        {
                        // Handle Foo events
                        }

                        void handleEvent(con st Event& e)
                        {
                        // General event handler
                        }
                        };

                        --
                        Erik Wikström

                        Comment

                        • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

                          #13
                          Re: How to make every derived class to return a different int

                          On 2008-09-23 20:32, Erik Wikström wrote:
                          The second alternative (which I think might be a bit more elegant) is to
                          make the event handlers member-functions of state-objects:
                          >
                          >
                          struct Event {};
                          struct FooEvent : public Event {};
                          >
                          struct State {};
                          >
                          struct BarState : public State
                          {
                          void handleEvent(con st FooEvent& e)
                          {
                          // Handle Foo events
                          }
                          >
                          void handleEvent(con st Event& e)
                          {
                          // General event handler
                          }
                          };

                          Actually, that won't work (remind me not to write code when I'm tired),
                          you would need something like double dispatch to get it to work.

                          --
                          Erik Wikström

                          Comment

                          • Victor Bazarov

                            #14
                            Re: How to make every derived class to return a different int

                            Kai-Uwe Bux wrote:
                            Stefano Sabatini wrote:
                            [snip]
                            >Yes, I tried it and it is indeed what I need. Only what I also need
                            >would be a static method which returns the total number of objects
                            >already registered.
                            >
                            Objects or classes?
                            >
                            Assuming classes, this poses an interesting problem. Here are two attempts:
                            >
                            a)
                            >
                            class reg_base {
                            protected:
                            >
                            static
                            unsigned int &
                            the_count ( void ) {
                            static unsigned int c = 0;
                            return ( c );
                            }
                            >
                            static
                            unsigned int count ( void ) {
                            return ( the_count() ++ );
                            }
                            >
                            public:
                            >
                            static
                            unsigned int num_classes ( void ) {
                            return ( the_count() );
                            }
                            >
                            virtual
                            unsigned int get_id ( void ) const = 0;
                            >
                            virtual
                            ~reg_base ( void ) {}
                            >
                            };
                            >
                            template < typename D >
                            class reg : public reg_base {
                            >
                            static unsigned int const the_id;
                            >
                            public:
                            >
                            unsigned int get_id ( void ) const {
                            return ( the_id );
                            }
                            >
                            static
                            unsigned int id ( void ) {
                            return ( the_id );
                            }
                            >
                            virtual
                            ~reg ( void ) {}
                            >
                            };
                            >
                            template < typename D >
                            unsigned int const reg<D>::the_id = reg<D>::reg_bas e::count();
                            >
                            >
                            struct X : public reg<X{};
                            struct Y : public reg<Y{};
                            struct Z : public reg<Z{};
                            >
                            #include <iostream>
                            >
                            int main ( void ) {
                            std::cout << "Classes: " << reg_base::num_c lasses() << '\n';
                            >
                            X x;
                            Y y1;
                            Y y2;
                            reg_base * px = new X ();
                            reg_base * py = new Y ();
                            >
                            std::cout << "X " << x.get_id() << '\n';
                            std::cout << "Y " << y1.get_id() << '\n';
                            std::cout << "Y " << y2.get_id() << '\n';
                            >
                            std::cout << "X " << px->get_id() << '\n';
                            std::cout << "Y " << py->get_id() << '\n';
                            >
                            std::cout << "X " << X::id() << '\n';
                            std::cout << "Y " << Y::id() << '\n';
                            >
                            delete ( px );
                            delete ( py );
                            }
                            >
                            >
                            This one does not count the class Z. Honestly, I don't know the reason.
                            Most likely, the optimizer throws Z away (and the instantiation of the
                            base class as well), since it isn't used anywhere in the program. Built
                            without optimization with VC++ 2008 (the "Debug" configuration), the
                            program reports 3 classes, built optimized it reports only 2.
                            [..]
                            >
                            >
                            Best
                            >
                            Kai-Uwe Bux
                            V
                            --
                            Please remove capital 'A's when replying by e-mail
                            I do not respond to top-posted replies, please don't ask

                            Comment

                            • Kai-Uwe Bux

                              #15
                              Re: How to make every derived class to return a different int

                              Victor Bazarov wrote:
                              Kai-Uwe Bux wrote:
                              [snip]
                              >class reg_base {
                              >protected:
                              >>
                              > static
                              > unsigned int &
                              > the_count ( void ) {
                              > static unsigned int c = 0;
                              > return ( c );
                              > }
                              >>
                              > static
                              > unsigned int count ( void ) {
                              > return ( the_count() ++ );
                              > }
                              >>
                              >public:
                              >>
                              > static
                              > unsigned int num_classes ( void ) {
                              > return ( the_count() );
                              > }
                              >>
                              > virtual
                              > unsigned int get_id ( void ) const = 0;
                              >>
                              > virtual
                              > ~reg_base ( void ) {}
                              >>
                              >};
                              >>
                              >template < typename D >
                              >class reg : public reg_base {
                              >>
                              > static unsigned int const the_id;
                              >>
                              >public:
                              >>
                              > unsigned int get_id ( void ) const {
                              > return ( the_id );
                              > }
                              >>
                              > static
                              > unsigned int id ( void ) {
                              > return ( the_id );
                              > }
                              >>
                              > virtual
                              > ~reg ( void ) {}
                              >>
                              >};
                              >>
                              >template < typename D >
                              >unsigned int const reg<D>::the_id = reg<D>::reg_bas e::count();
                              >>
                              >>
                              >struct X : public reg<X{};
                              >struct Y : public reg<Y{};
                              >struct Z : public reg<Z{};
                              >>
                              >#include <iostream>
                              >>
                              >int main ( void ) {
                              > std::cout << "Classes: " << reg_base::num_c lasses() << '\n';
                              >>
                              > X x;
                              > Y y1;
                              > Y y2;
                              > reg_base * px = new X ();
                              > reg_base * py = new Y ();
                              >>
                              > std::cout << "X " << x.get_id() << '\n';
                              > std::cout << "Y " << y1.get_id() << '\n';
                              > std::cout << "Y " << y2.get_id() << '\n';
                              >>
                              > std::cout << "X " << px->get_id() << '\n';
                              > std::cout << "Y " << py->get_id() << '\n';
                              >>
                              > std::cout << "X " << X::id() << '\n';
                              > std::cout << "Y " << Y::id() << '\n';
                              >>
                              > delete ( px );
                              > delete ( py );
                              >}
                              >>
                              >>
                              >This one does not count the class Z. Honestly, I don't know the reason.
                              >
                              Most likely, the optimizer throws Z away (and the instantiation of the
                              base class as well), since it isn't used anywhere in the program. Built
                              without optimization with VC++ 2008 (the "Debug" configuration), the
                              program reports 3 classes, built optimized it reports only 2.
                              [snip]

                              Hm, interesting.

                              That indicates, that the output is either undefined or implementation
                              defined. That in turn poses the question, where in the program I invoke
                              undefined or implementation defined behavior. Got to take a closer look; as
                              of now, I am quite puzzled.


                              Best

                              Kai-Uwe Bux

                              Comment

                              Working...