Macro question (C++)

Started by
12 comments, last by d000hg 17 years, 11 months ago
Quote:Original post by Nitage
He should be careful with the CREATE_FUNCTOR identifier as it's a macro, but the _name identifier is fine, as it obeys scoping rules.

I don't think you quite understand. The point is that the user--who shouldn't have to know what identifiers are being generated by CREATE_FUNCTOR--may end up using exactly that name, and then becoming quite confused when it collides with an identifier he doesn't know he's already defined.
Advertisement
Quote:Original post by Zahlman
Quote:Original post by d000hg
I have a macro which is something like this:
#define CREATE_FUNCTOR(name,method) struct name {  void method(); };

This isn't exact so don't focus on why I want to do this!


Sorry, I must insist. You are aware of std::mem_fun and std::mem_fun_ref, yes? I'm pretty sure there's *something* that solves your problem more nicely...


I don't think I can use these but I'll try and remember to check. In fact you can see the real macros...
#define CREATE_HANDLER(DLG_NAME,HANDLER_NAME) /void HANDLER_NAME(); /struct HANDLER_NAME##_functor : public GUIEventHandlerBase /{ /	DLG_NAME *m_pThis; /	inline void On() { m_pThis->HANDLER_NAME(); } /	HANDLER_NAME##_functor(DLG_NAME *pThis) : m_pThis(pThis){} /};#define REGISTER_HANDLER(ID,EVENT,HANDLER) RegisterEventHandler(ID,EVENT,new HANDLER##_functor(this));


And the way they are used in header and source file:
class MainMenuDlg : public GUIDialog  {protected:	const static std::string Template;	GameState *m_pGameState;public:	MainMenuDlg(GUIManager *pManager,GameState *pGameState);	virtual ~MainMenuDlg();	void LoadSaveGame(char *name);	CREATE_HANDLER(MainMenuDlg , OnQuit)	CREATE_HANDLER(MainMenuDlg , OnLoad)	CREATE_HANDLER(MainMenuDlg , OnNewGame)};


const std::string MainMenuDlg::Template = "MainMenu";MainMenuDlg::MainMenuDlg(GUIManager *pManager,GameState *pGameState): GUIDialog(pManager,Template), m_pGameState(pGameState){	SetPos(0,0);	SetSize(1,1);	m_pGUIManager->LockWindow(this,true);	REGISTER_HANDLER("BTN_EXIT",BUTTON_LCLICK,OnQuit)	REGISTER_HANDLER("BTN_NEW",BUTTON_LCLICK,OnNewGame)	REGISTER_HANDLER("BTN_LOAD",BUTTON_LCLICK,OnLoad)}void MainMenuDlg::OnQuit(){}	void MainMenuDlg::OnLoad(){}void MainMenuDlg::OnNewGame(){}


The macros are ugly but the end result is quite nice - not safe or proper C++ I'm sure - I want the user to have it this easy to use but not have to resort to nasty macros (as much) if possible.
Something like this should do it:

template <typename DLG>class boundPfn : public GUIEventHandlerBase {  typedef DLG::void(*)() pfn_t;  DLG * dlg;  pfn_t pfn;  boundPfn(DLG* dlg, pfn_t pfn) : dlg(dlg), pfn(pfn) {}  void operator()() { ((*dlg).*(pfn)); }  // why use a member function rather than operator() overload?};// This macro is kinda marginal... Normally this kind of work would be done// with a function (in order to infer type for class instantiation), but this// saves a little more typing over that approach#define REGISTER_EVENT(id, event, classname, handler) RegisterEventHandler(id, event, new boundPfn<classname>(this, &##classname##::##handler))// In MainMenuDlgREGISTER_EVENT("BTN_EXIT", BUTTON_LCLICK, MainMenuDlg, OnQuit);


As an added bonus (heh), you only declare one extra type per DLG class, rather than one extra type per handler.
That looks like I can just drop it in and replace my existing #define - I'll give it a try because it looks a bit nicer.

Thanks.

This topic is closed to new replies.

Advertisement