Boost logo

Boost :

From: Jonathan Wang (babysloth_at_[hidden])
Date: 2003-02-14 10:01:09


Hi Aleksey,

>Hmm, interesting. So, basically, the "select" has the semantics of
>"mixed" (half run-time, half compile-time) 'find_if' - it takes
>a compile-time sequence and a run-time predicate, and iterates the
>former until the predicate is satisfied (or it reaches the end of the
>sequence). We can "return" the search result by passing another
>function object that will be called when something is found:

[snip the code]

That's right:-)

>Does it make sense to you?

Yes. It's started when reading the FSM example. In the member function state_machine<>::do_transition(), serveral templates(aux::STT_impl_gen, aux::STT_void_row_impl, ...) are used to process the events. I wonder if there's any generic way, which can be as simple as "for_each". The "select" may simplify the implementation of the FSM, for we just need to write a predicate to check the current state and the event. If satisfied, invoke the correspond function and change current state.

Also the "select" could be used to "generate" WndProc in windows message mapping:

  // <WindowsMessage, MessageProc>
  template <UINT M, void (*H)(HWND, WPARAM, LPARAM)>
  struct handler_c
  {
        enum {value = M};
        static void do_handle(HWND hwnd, WPARAM wParam, LPARAM lParam)
        {
                H(hwnd, wParam, lParam);
        }
  };

  // generic message map base
  template <typename T>
  class MessageMap
  {
  private:

        // the predicate for checking and invoking
        class msg_handler
        {
        private:
            HWND hwnd_;
            UINT message_;
            WPARAM wParam_;
            LPARAM lParam_;
        public:
            msg_handler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                : hwnd_(hwnd), message_(message), wParam_(wParam), lParam_(lParam) {}
       
            template< typename U > bool operator()(U x)
            {
               if(U::value == message_)
               {
                       U::do_handle(hwnd_, wParam_, lParam_);
                       return true;
               }
               return false;
            }
        };
  public:
        LRESULT process_message(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        {
                if(mpl::select<
                    T::msg_table
>(msg_handler(hwnd, message, wParam, lParam)))
                        return 0;
                return DefWindowProc(hwnd, message, wParam, lParam);
        }
  };

  // user-defined message map
  class MyMessageMap: public MessageMap<MyMessageMap>
  {
  public:
        typedef mpl::vector<
            handler_c<WM_CREATE, on_create>,
            handler_c<WM_TIMER, on_timer>,
            handler_c<WM_KEYDOWN, on_keydown>,
            handler_c<WM_LBUTTONDOWN, on_mousedown>,
            handler_c<WM_RBUTTONDOWN, on_mousedown>,
            handler_c<WM_PAINT, on_paint>,
            handler_c<WM_DESTROY, on_destroy>
>::type msg_table;
  };

  LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
        MyMessageMap m;
        return m.process_message(hwnd, message, wParam, lParam);
  }

And it can generate code like:

  LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
        switch(message)
        {
            case WM_CREATE:
                on_create(hwnd, wParam, lParam);
                return 0;
            case WM_TIMER:
                on_timer(hwnd, wParam, lParam:
                return 0;
                ...
        }
        return DefWindowProc(hwnd, wParam, lParam);
  }

Regards,

Jonathan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk