Archived

This topic is now archived and is closed to further replies.

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

This topic is 5775 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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 function

LRESULT 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;
}
}


Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
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.



Oh, I thought we''re just talking about event/message
handling for Windows (or whatever).


Premature optimizations can only slow down your project even more.

Share this post


Link to post
Share on other sites
quote:
Original post by tangentz
Oh, I thought we''re just talking about event/message
handling for Windows (or whatever).


We were. Message despatching is not mutually exclusive with state machines. Far from it.

--
The Dilbert Principle: People are idiots.

Share this post


Link to post
Share on other sites
>>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

You''re actually not just doing a std::map, you''re really using
std::map,std::alloc>,int,std::less,std::alloc>,std::alloc>

It''s not really hard to exceed that 255 char limit once you get going =)

By the way, VC.NET doesn''t have that warning.

Share this post


Link to post
Share on other sites
Make sure the #pragma is the first line of the file, or near enough. A lot of people report that it doesn''t work, but I''ve always found that it does if it comes before all the #includes.

And the member function as windows callback question comes up almost literally every day - do search the forums before posting.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost ]

Share this post


Link to post
Share on other sites