Sign in to follow this  
d000hg

Macro question (C++)

Recommended Posts

d000hg    1199
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! My problem is that I want the struct to be called _name, not name. If I change the macro to be:
#define CREATE_FUNCTOR(name,method) struct _name {  void method(); };
Then I get a struct called "_name". Is it possible to get the preproccesor to understand I want to stick '_' onto the front of the variable? (It's actually for a message handling thing and I want to create a functor called _OnXXX for each event-handler OnXXX)

Share this post


Link to post
Share on other sites
d000hg    1199
Thanks guys. I agree it's ugly to use macros for this at all but I don't think C++ makes what I want possible through normal means (I'm making something a little like MFC).

Share this post


Link to post
Share on other sites
Sneftel    1788
It is in particular naughty to just use an underscore, though, because it is extremely likely that someone using your framework will want to use that name. Don't make it _whatever. At the very least, make it __AUTO__d000hgsframework__whatever or suchlike.

Share this post


Link to post
Share on other sites
Nitage    1107
Quote:
Original post by Sneftel
It is in particular naughty to just use an underscore, though, because it is extremely likely that someone using your framework will want to use that name. Don't make it _whatever. At the very least, make it __AUTO__d000hgsframework__whatever or suchlike.


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.

Also, the identifier __AUTO__d000hgsframework__ is reserved to the compiler and standard library.

Share this post


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

Share this post


Link to post
Share on other sites
swiftcoder    18437
Quote:
Original post by Zahlman
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...


And if those don't do what you need, how about boost::function and boost::bind?
I can guarrentee they will do more than you can do with your macros [grin]

Share this post


Link to post
Share on other sites
demonkoryu    980
Quote:
Original post by Nitage
[...]
Also, the identifier __AUTO__d000hgsframework__ is reserved to the compiler and standard library.


</sarcasm>.

May I conclude that you think using identifiers like this is OK, in spite of the holy?

To come out, yes, I use #ifndef __MYFREAKINGFILENAME_H... all the time. [smile]

Share this post


Link to post
Share on other sites
rip-off    10979
Quote:
Original post by Konfusius
Quote:
Original post by Nitage
[...]
Also, the identifier __AUTO__d000hgsframework__ is reserved to the compiler and standard library.


</sarcasm>.

May I conclude that you think using identifiers like this is OK, in spite of the holy?

To come out, yes, I use #ifndef __MYFREAKINGFILENAME_H... all the time. [smile]


Why type 2 extra characters just to risk breaking your program? [smile]

Share this post


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

Share this post


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

Share this post


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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this