lundi 11 octobre 2010

What do programmers do when they are bored ?

Ok so I have not posted in a long time because I've been very busy with my uni stuff; so I thought I might share a nice little trick I developed quickly this morning.

Yes I was very bored and skimming through DXUT source file when I spotted those:
#define SET_ACCESSOR( x, y )       inline void Set##y( x t )   { DXUTLock l; m_state.m_##y = t; };
#define GET_ACCESSOR( x, y )       inline x Get##y()           { DXUTLock l; return m_state.m_##y; };
#define GET_SET_ACCESSOR( x, y )   SET_ACCESSOR( x, y ) GET_ACCESSOR( x, y )

#define SETP_ACCESSOR( x, y )      inline void Set##y( x* t )  { DXUTLock l; m_state.m_##y = *t; };
#define GETP_ACCESSOR( x, y )      inline x* Get##y()          { DXUTLock l; return &m_state.m_##y; };
#define GETP_SETP_ACCESSOR( x, y ) SETP_ACCESSOR( x, y ) GETP_ACCESSOR( x, y )

and I instantly wanted the same type of macros, except with all the genericity and safety of C++0x.

Setters were a walk in the park:
#define Nitro_PropertySet(name)    inline void set##name(decltype(m##name) t) { m##name = t; }

Getters not so much; I initially thought that I could use the trailing-type feature of C++0x to get an auto-magic return type, unfortunately it behaves differently and would not accept the member name for an answer.
So I used a little trick, I declare a template structure with a default template parameter (the decltype with the member name), add a typedef, inject the whole in the inline getters and there it is !

#define Nitro_PropertyGet(name)    template < typename T = decltype(m##name)> struct __##name { typedef typename T type; }; inline __##name<>::type get##name() { return m##name; }

For a member named mNumSplits, that expands to:
 template < typename T = decltype(mNumSplits)>
 struct __mNumSplits { typedef typename T type; };
 inline __mNumSplits<>::type getNumSplits() { return mNumSplits; }

Neat. And all that while eating breakfast :)