I am trying to take the ideas from Is it possible to write a template to check for a function's existence? and apply them, but I am running into some trouble. I have the following defined:
#define HAS_MEM_FUNC(func, name) \
template<typename T, typename Sign> \
struct name {\
typedef char yes[1]; \
typedef char no[2]; \
template <typename U, U> struct type_check; \
template <typename _1> static yes &chk(type_check<Sign, &_1::func> *); \
template <typename > static no &chk(...); \
static bool const value = sizeof(chk<T>(0)) == sizeof(yes); \
}
// Creates a member function detector and two overloads of a message handler
// registration function, one that registers a member function of a specific name
// if it exists and another that does nothing if that member function doesn't exist.
#define DEFINE_REGISTER_FUNC(msgid, msgtype, handlername) \
HAS_MEM_FUNC(handlername, has_##handlername);\
template <typename T>\
static void register_##handlername(\
T* pWnd, \
typename std::enable_if<has_##handlername<T, void(T::*)(msgtype&)>::value, T>::type* t = nullptr) \
{\
(void) t;\
pWnd->setMessageHandler(\
msgid,\
Handler<msgtype>(std::bind(&T::handlername, pWnd, std::placeholders::_1)));\
}\
\
template <typename T> \
static void register_##handlername(\
T* pWnd, \
typename std::enable_if<!has_##handlername<T, void(T::*)(msgtype&)>::value, T>::type* t = nullptr) \
{\
(void)pWnd;\
(void)t;\
}
I also have a class defined like this:
template <typename T>
class RegisterHandlers
{
public:
template <typename T>
static void registerHandlers(T* pWnd)
{
register_onCreate(pWnd);
register_onPaint(pWnd);
}
private:
DEFINE_REGISTER_FUNC(WM_CREATE, CreateMessage, onCreate);
DEFINE_REGISTER_FUNC(WM_PAINT, PaintMessage, onPaint);
};
The idea is that if the class T
has a member function onCreate(CreateMessage&)
, it will automatically be registered as the handler for WM_CREATE
. If it has no such method, then the do-nothing overload of register_onCreate
will be called and the compiler will be happy. Same for the onPaint handler (I included that mostly to illustrate that the SFINAE does work).
This works fine if I have a class like this:
class MainWnd
{
public:
friend class RegisterHandlers<MainWnd>;
MainWnd()
{
RegisterHandlers<MainWnd>::registerHandlers(this);
}
protected:
void onCreate(CreateMessage&) { /* do some stuff */ }
};
However, the moment I add this:
class SubWnd : public MainWnd
{
public:
friend class RegisterHandlers<SubWnd>;
SubWnd()
{
RegisterHandlers<SubWnd>::registerHandlers(this);
}
protected:
void onPaint(PaintMessage&) { /* do some stuff */ }
};
I get an error that MainWnd::onCreate
is inaccessible (cannot access protected member). I broke down the macros to help find where the problem is actually occurring, and it seems to be in the HAS_MEM_FUNC
macro, probably at this line:
template <typename _1> static yes &chk(type_check<Sign, &_1::func> *);
So, I have two questions really:
- Is it possible to do what I am trying to do without making the event handlers public?
- Is it also possible to avoid re-registering event handlers if the base class already did it? Phrased another way, is there a way to tell if the function was declared in the base class or if it originated in the derived class?
In case it's relevant, I am trying to do this on the Visual Studio 2013 Preview compiler. The motivation for this question is that I am experimenting with C++11 features and Windows API wrappers, and I am trying to see if there are better solutions than large vtables and message map macros for routing messages to an appropriate handler.