std::map issues, and pointer-to-function question

Started by
14 comments, last by daerid 22 years, 1 month ago
Question 1: Whenever I use a std::map in my project, I always get the "Identifier truncated to 255 characters in Debug information" warning, even if I''m just doing a std::map. How do I fix that? Or do I just have to use the #pragma warning(disable:####) method? (Using VC++ 6 SP5 btw) Question 2: I''m basically writing my own c++ object library for Win32 API. What I''d like to do is use pointer-to-member-functions as the callbacks for windows messages, and use a std::map to link up the WM_*** message ( an unsigned integer ) with the pointer to the function. However, I can''t seem to get it quite right. Here''s some code for example:
  

class Window;

// Pointer to a member function of the Window class

// that returns an LRESULT and takes a WPARAM and 

// a LPARAM as arguments

typedef LRESULT (Window::*MSGCALLBACK)(WPARAM,LPARAM);

class Window
{
  // ... some code

public:
  Window(); 

  // Add a message handler

  void AddMsgHandler(UINT msg,MSGCALLBACK pfn);
  
  // Handle the WM_CHAR message

  LRESULT OnChar(WPARAM wparam,LPARAM lparam);

  // ... some more code

protected:
  std::map<UINT,MSGCALLBACK> _msgmap;
};

// Implementation

Window::Window
{
  // Add the WM_CHAR msg handler

  AddMsgHandler(WM_CHAR,reinterpret_cast<MSGCALLBACK>(Window::OnChar));
}

void Window::AddMsgHandler(UINT msg,MSGCALLBACK pfn)
{
  _msgmap.insert(std::pair<UINT,MSGCALLBACK>(msg,pfn));
}

LRESULT Window::OnChar(WPARAM wparam,LPARAM lparam)
{
  // process and display char message here

  ...
  ...
}

  
Am I missing something? Whenever I try to compile the code above, I get "Error: reinterpret_cast, cannot convert '''' to ''__thiscall long (Window::*)(WPARAM,LPARAM);'' or something to that effect. What am I doing wrong? Thanks in advance!
daerid@gmail.com
Advertisement

Question 1:

You basically can two options:

1. Ignore the warning (duh)
2. Put a #pragma warning(disable:4786) at the top

It''s a well-known "problem" with VC++.

Question 2:

Just two comments:

You don''t need the reinterpret_cast.

  AddMsgHandler(WM_CHAR,OnChar);  


Using a switch statement may actually be MORE desirable.
(or until hash table becomes standard)

Why?

You can put the most often-used cases at the top of the
switch. You can''t control how the map is laid out.


Premature optimizations can only slow down your project even more.
神はサイコロを振らない!
Herm... kewl.

Thanks

I don''t want to use a switch statement because I want to be able to dynamically add and remove message handlers at run time.
daerid@gmail.com
I used a slightly different mapping method:

  typedef void (*tyMessageHandler)(Window *wnd, /* other args */);typedef std::map<long, tyMessageHandler> tyMessageMap;.class Window{  //...  tyMessageMap m_MessageMap;};  


You can now insert simple functions into the message map without having to derive from or reimplement the Window class.

I wanna work for Microsoft!
[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!

Just like in another thread, it begs the question,
why would you want to "be able to dynamically add and
remove message handlers at run time"?

IMHO, Message handlers should be "static".

Maybe an example of why you "need" it to be dynamic
would help.


Premature optimizations can only slow down your project even more.
神はサイコロを振らない!
quote:Original post by tangentz

Just like in another thread, it begs the question,
why would you want to "be able to dynamically add and
remove message handlers at run time"?

IMHO, Message handlers should be "static".

Maybe an example of why you "need" it to be dynamic
would help.

See the reply in the other thread. I write general-purpose Windows UI code, and being able to manage certain objects using this one lightweight class (and only as much code as I need) is an advantage for me.

I wanna work for Microsoft!
[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!
Interesting approach Olesuyi, but I fail to see why you would pass a pointer to a window object.

here''s a sample of what my WNDPROC would be ( pseudo-code ):

  LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam){  Window *win;   bool doDef;  LRESULT res;  win = g_pApp->GetWindow(hwnd);  res = win->DispatchMsg(msg,wparam,lparam,doDef);  return doDef?::DefWindowProc(hwnd,msg,wparam,lparam):res;}// The DispatchMsg functionLRESULT Window::DispatchMsg(UINT msg,WPARAM wparam,LPARAM lparam, bool &doDef){  std::map<UINT,MSGCALLBACK>::iterator pos;  pos = _msgmap.find(msg);  if(pos!=_msgmap.end())  {    doDef = false;    return (*pos)(wparam,lparam);  }  else  {    doDef = true;    return 0;  }}  


daerid@gmail.com
The difference is that my static MessageRouter function also does the dispatch (and if there is no handler defined in that class, the default window procedure is called instead).

O L U S E Y I. It''s not that hard to spell.

I wanna work for Microsoft!
[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!
quote:Original post by tangentz
Just like in another thread, it begs the question,
why would you want to "be able to dynamically add and
remove message handlers at run time"?


Several reasons, I guess. It''s not too hard to imagine implementing a state machine using this sort of technique - i.e. you could modify the runtime behaviour of an event according to the current state.

--
The Dilbert Principle: People are idiots.
quote:Original post by Oluseyi
O L U S E Y I. It's not that hard to spell.


:o

sorry.. it's just not a word I'm used to typing

edit: I just understood. That's pretty nifty

Edited by - daerid on February 18, 2002 1:38:30 PM
daerid@gmail.com

This topic is closed to new replies.

Advertisement