Auto dispatch metaprogramming tricks

I would like to dispatch messages to a class based simply on the *presence*
of a message handler method.
Currently, the classes maintain an MPL vector of the messages they handle
and must implement a on(message

AMDG Alexander Lamaison wrote:
I would like to dispatch messages to a class based simply on the *presence* of a message handler method.
Currently, the classes maintain an MPL vector of the messages they handle and must implement a on(message
) method for each one. The dispatcher uses this compile-time list to build the dispatching code. This means the information is maintained twice and may fall out of sync (e.g. adding the handler but forgetting to update the message vector. Are there any template metaprogramming tricks I can employ to dispatch the message to a handler method if it exists and the default handler otherwise? All this information is available at compile time. The question is are templates are powerful enough to make use of it?
Yes. The code looks something like this:
typedef char no;
struct yes { char dummy[2]; };
struct has_on_result {
has_on_result operator,(int);
};
no check_on_result(const has_on_result&);
yes check_on_result(...);
template<class T>
struct has_on_impl : T {
using T::on;
has_on_result on(...);
};
template
{};
In Christ, Steven Watanabe

Zitat von Steven Watanabe
Yes. The code looks something like this:
typedef char no; struct yes { char dummy[2]; };
struct has_on_result { has_on_result operator,(int); };
no check_on_result(const has_on_result&); yes check_on_result(...);
template<class T> struct has_on_impl : T { using T::on; has_on_result on(...); };
template
struct has_on : boost::mpl::bool_< sizeof(check_on_result(((has_on_impl<T>*)0)->on(*((M*)0)) , 0)) != sizeof(no) {};
how does this work with member functions that have a "void" result? does it? how does this work at all? "using T::on" is invalid when T doesn't have "on", so the instantiation of has_on<>, that should result in mpl::false_, fails. do you have a link to actual code that uses this? thanks

AMDG strasser@uni-bremen.de wrote:
Zitat von Steven Watanabe
: Yes. The code looks something like this:
typedef char no; struct yes { char dummy[2]; };
struct has_on_result { has_on_result operator,(int); };
no check_on_result(const has_on_result&); yes check_on_result(...);
template<class T> struct has_on_impl : T { using T::on; has_on_result on(...); };
template
struct has_on : boost::mpl::bool_< sizeof(check_on_result(((has_on_impl<T>*)0)->on(*((M*)0)) , 0)) != sizeof(no) {};
how does this work with member functions that have a "void" result? does it?
It handles void. That's what the comma operator is for.
how does this work at all? "using T::on" is invalid when T doesn't have "on", so the instantiation of has_on<>, that should result in mpl::false_, fails.
Requiring at least one overload of on, is not particularly onerous in this context. If you're willing to require the exact signature, you can use SFINAE as in Kim's post.
do you have a link to actual code that uses this?
I think proto uses something like this for operator(). There are a few extra tricks that work for this however. In Christ, Steven Watanabe

Steven Watanabe schrieb:
AMDG
Alexander Lamaison wrote:
I would like to dispatch messages to a class based simply on the *presence* of a message handler method.
Currently, the classes maintain an MPL vector of the messages they handle and must implement a on(message
) method for each one. The dispatcher uses this compile-time list to build the dispatching code. This means the information is maintained twice and may fall out of sync (e.g. adding the handler but forgetting to update the message vector. Are there any template metaprogramming tricks I can employ to dispatch the message to a handler method if it exists and the default handler otherwise? All this information is available at compile time. The question is are templates are powerful enough to make use of it?
Hi Alexander, here is a class that i use to check the existence of a member function. It works on MSVC 9. But as indicated by strasser ( sorry, cant find your name in the email) it might be not portable.
template<typename T>
struct HasSizeMethod
{
private:
template
Yes. The code looks something like this:
typedef char no; struct yes { char dummy[2]; };
struct has_on_result { has_on_result operator,(int); };
no check_on_result(const has_on_result&); yes check_on_result(...);
template<class T> struct has_on_impl : T { using T::on; has_on_result on(...); };
template
struct has_on : boost::mpl::bool_< sizeof(check_on_result(((has_on_impl<T>*)0)->on(*((M*)0)) , 0)) != sizeof(no) {};
Hi Steve,
as indicated by strasser i have also difficulties to compile your code.
But your code seems to be more generic, since you dont need to provide
the result_type of the member function.
Can you provide a working example?
# include
{};
struct has_on_struct
{
int on(int ) const
{
return 1;
}
};
struct arbitrary_struct
{
int no(int) const
{
return 1;
}
};
int main()
{
BOOST_MPL_ASSERT((has_on
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

AMDG Kim Kuen Tang wrote:
as indicated by strasser i have also difficulties to compile your code. But your code seems to be more generic, since you dont need to provide the result_type of the member function.
Can you provide a working example?
A couple bugs:
* CV qualifiers we're causing an ambiguity.
* I missed a pair of parentheses.
* At least one overload of on is required.
The following compiles for me:
#include
{};
struct has_on_struct {
int on(int) const
{
return 1;
}
};
struct arbitrary_struct {
int on(void*) const
{
return 1;
}
};
int main() {
BOOST_MPL_ASSERT((has_on

My introspection lib in the vault should have macro to generate all of this automatically

Steven Watanabe schrieb:
AMDG
Kim Kuen Tang wrote:
as indicated by strasser i have also difficulties to compile your code. But your code seems to be more generic, since you dont need to provide the result_type of the member function.
Can you provide a working example?
Thx for providing a working example.
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

(see my comments below)
----- Original Message -----
From: "Steven Watanabe"
AMDG
Alexander Lamaison wrote:
I would like to dispatch messages to a class based simply on the *presence* of a message handler method.
Currently, the classes maintain an MPL vector of the messages they handle and must implement a on(message
) method for each one. The dispatcher uses this compile-time list to build the dispatching code. This means the information is maintained twice and may fall out of sync (e.g. adding the handler but forgetting to update the message vector. Are there any template metaprogramming tricks I can employ to dispatch the message to a handler method if it exists and the default handler otherwise? All this information is available at compile time. The question is are templates are powerful enough to make use of it?
Yes. The code looks something like this:
typedef char no; struct yes { char dummy[2]; };
struct has_on_result { has_on_result operator,(int); };
no check_on_result(const has_on_result&); yes check_on_result(...);
template<class T> struct has_on_impl : T { using T::on; has_on_result on(...); };
template
struct has_on : boost::mpl::bool_< sizeof(check_on_result(((has_on_impl<T>*)0)->on(*((M*)0)) , 0)) != sizeof(no) {};
In Christ, Steven Watanabe
I think what Mr. Lamaison wants is:
give a message "handler" class like...
class Handler {
void on(const M1&);
void on(const M2&);
void on(const M3&);
};
... is it possible to deduce ...
typedef mpl::vector

Firstly, thank you everyone for your replies. There are amazing minds here. On Fri, 21 May 2010 09:37:08 -0500, Terry Golubiewski wrote:
From: "Steven Watanabe"
Alexander Lamaison wrote:
I would like to dispatch messages to a class based simply on the *presence* of a message handler method.
Currently, the classes maintain an MPL vector of the messages they handle and must implement a on(message
) method for each one. The dispatcher uses this compile-time list to build the dispatching code. This means the information is maintained twice and may fall out of sync (e.g. adding the handler but forgetting to update the message vector. Are there any template metaprogramming tricks I can employ to dispatch the message to a handler method if it exists and the default handler otherwise? All this information is available at compile time. The question is are templates are powerful enough to make use of it?
I think what Mr. Lamaison wants is: give a message "handler" class like...
class Handler { void on(const M1&); void on(const M2&); void on(const M3&); };
... is it possible to deduce ...
typedef mpl::vector
HandledMessages; ... without knowing a priori the list of possible message messages
typedef mpl::vector
PosssibleMessages;
This is exactly what I'm trying to do.
Because, if you have to maintain PossibleMessages, then when a new message is added, the user would have to update PossibleMessages and and a method to "Handler", which is still two changes; i.e. no better. Then again, filtering PossibleMessage using your "has_on" filter (using mpl::remove_if?) would be better if we assume that the list of PossibleMessages doesn't change very often, but users do regularly make Handlers that respond to various message subsets.
You have explained this much better than I did. This is precisely the
situation I'm in.
So it seems that there are several pieces of code (thanks!) that give me a
compile-time predicate indicating whether the handler method is present
(I'm not sure if they differ in the details? The implementations certainly
look quite different; Steven and Terry's in particular). As Terry points
out, there is a second half to the problem: how to dispatch arbitrary
messages?
To make it more concrete, I should explain that I'm dealing with Windows
window messages (e.g. WM_CREATE, WM_SETTEXT etc.) which are unsigned ints.
I dispatch these to handlers with the signature:
LRESULT on(message

template<> class message
{ ... } template<> class message { ... } So there is in fact a list of 'PossibleMessages' available to the compiler. It is every argument to a specialisation of class message<Id>. Is there a way I can harvest these to build the PossibleMessages list?
Derive message<T> from a "tag" base class. Then you don't build a list, but you have a predicate to test "is this type in my set?" by using is_base_of, that's perfectly useful for enable_if. On the other hand, you could use a signature that matches the use of the template: template<typename Msg> LRESULT on (message<T> m); will only match this templatized member function if it is indeed a specialization of message. BTW, I take a different approach to the problem in general. Rather than a zillion individual handlers, I use small "pods" of related messages. For example, handling the mouse messages is a class that handles just a few mouse-related messages, and if you deal with one you probably deal with all. The pods are kept in a linked list, which is searched for suitable handlers. This allows run-time "modes" by updating that list or enabling specific entries that lie dormant. By having different specially declared functions for each Windows message (yet, not a million virtual functions in one class!) each can have a proper signature that wraps its real use, rather than dealing with the raw format. See also http://www.dlugosz.com/Repertoire/refman/Tomahawk/message_crack.html, which might give you some ideas that fit with your current scheme. --John TradeStation Group, Inc. is a publicly-traded holding company (NASDAQ GS: TRAD) of three operating subsidiaries, TradeStation Securities, Inc. (Member NYSE, FINRA, SIPC and NFA), TradeStation Technologies, Inc., a trading software and subscription company, and TradeStation Europe Limited, a United Kingdom, FSA-authorized introducing brokerage firm. None of these companies provides trading or investment advice, recommendations or endorsements of any kind. The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

On Fri, 21 May 2010 17:50:20 -0400, John Dlugosz wrote:
template<> class message
{ ... } template<> class message { ... } So there is in fact a list of 'PossibleMessages' available to the compiler. It is every argument to a specialisation of class message<Id>. Is there a way I can harvest these to build the PossibleMessages list?
Derive message<T> from a "tag" base class. Then you don't build a list, but you have a predicate to test "is this type in my set?" by using is_base_of, that's perfectly useful for enable_if.
It's building this set that's the problem, not checking if an item is in it. I need a list of all messages IDs (UINTs) that have a message<BLAH> specialisation.
On the other hand, you could use a signature that matches the use of the template:
template<typename Msg> LRESULT on (message<T> m);
will only match this templatized member function if it is indeed a specialization of message.
Yes, this is how my handlers work (except the on() method is not itself a template - does that affect it?).
BTW, I take a different approach to the problem in general. Rather than a zillion individual handlers, I use small "pods" of related messages.
I'm building a native Windows Forms library so the public interface won't actually have any messages at all; only events. The stuff I'm doing now, however, is the intermediate layer so I still have to deal with messages.
For example, handling the mouse messages is a class that handles just a few mouse-related messages, and if you deal with one you probably deal with all. The pods are kept in a linked list, which is searched for suitable handlers.
How do you match the incoming message ID to the pods?
This allows run-time "modes" by updating that list or enabling specific entries that lie dormant. By having different specially declared functions for each Windows message (yet, not a million virtual functions in one class!) each can have a proper signature that wraps its real use, rather than dealing with the raw format.
I'm afraid I don't understand this bit. What do you mean by specially declared functions? Thanks. Alex

It's building this set that's the problem, not checking if an item is in it. I need a list of all messages IDs (UINTs) that have a message<BLAH> specialisation.
Why? I mean, what is the difference between pro-actively declaring all the allowed forms and recognizing an allowed for if/when it is presented? The trouble with "functional programming" is that you can't update a value. At run-time, you can imagine a constructor adds the instance to a linked list of all live instances. Compile-time MPL cannot do something similar: add itself to a list when a class is created. There is no changeable list, in principle. Perhaps you could have a script that greps for derived classes (some special marker you include to make it easy to notice) and generate another include file from that.
Yes, this is how my handlers work (except the on() method is not itself a template - does that affect it?).
I don't know enough about it to answer.
How do you match the incoming message ID to the pods?
[not Boost related] A declared range that each "commission" might be interested in, and a return value from the "minister" that the message just presented will _never_ be handled (so don't bother asking again).
... I'm afraid I don't understand this bit. What do you mean by specially declared functions?
Some details at http://www.dlugosz.com/Repertoire/refman/Tomahawk/message_parliament_guide.h.... For example, process_MouseMove takes parameters that are specific to WM_MOUSEMOVE, not generic msg or lParam values. It has a different signature than, say, process_Size (which handles WM_SIZE messages).
Thanks. Alex
TradeStation Group, Inc. is a publicly-traded holding company (NASDAQ GS: TRAD) of three operating subsidiaries, TradeStation Securities, Inc. (Member NYSE, FINRA, SIPC and NFA), TradeStation Technologies, Inc., a trading software and subscription company, and TradeStation Europe Limited, a United Kingdom, FSA-authorized introducing brokerage firm. None of these companies provides trading or investment advice, recommendations or endorsements of any kind. The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

Another thing to consider is that using a single type-list with over 100
message types will significantly (to me) slow compile time and may approach
compiler limits.
You can avoid these limits by grouping messages into related groups or by
using a dynamic dispatcher that registers callbacks at runtime
initialization.
terry
----- Original Message -----
From: "Alexander Lamaison"
Firstly, thank you everyone for your replies. There are amazing minds here.
On Fri, 21 May 2010 09:37:08 -0500, Terry Golubiewski wrote:
From: "Steven Watanabe"
Alexander Lamaison wrote:
I would like to dispatch messages to a class based simply on the *presence* of a message handler method.
Currently, the classes maintain an MPL vector of the messages they handle and must implement a on(message
) method for each one. The dispatcher uses this compile-time list to build the dispatching code. This means the information is maintained twice and may fall out of sync (e.g. adding the handler but forgetting to update the message vector. Are there any template metaprogramming tricks I can employ to dispatch the message to a handler method if it exists and the default handler otherwise? All this information is available at compile time. The question is are templates are powerful enough to make use of it?
I think what Mr. Lamaison wants is: give a message "handler" class like...
class Handler { void on(const M1&); void on(const M2&); void on(const M3&); };
... is it possible to deduce ...
typedef mpl::vector
HandledMessages; ... without knowing a priori the list of possible message messages
typedef mpl::vector
PosssibleMessages; This is exactly what I'm trying to do.
Because, if you have to maintain PossibleMessages, then when a new message is added, the user would have to update PossibleMessages and and a method to "Handler", which is still two changes; i.e. no better. Then again, filtering PossibleMessage using your "has_on" filter (using mpl::remove_if?) would be better if we assume that the list of PossibleMessages doesn't change very often, but users do regularly make Handlers that respond to various message subsets.
You have explained this much better than I did. This is precisely the situation I'm in.
So it seems that there are several pieces of code (thanks!) that give me a compile-time predicate indicating whether the handler method is present (I'm not sure if they differ in the details? The implementations certainly look quite different; Steven and Terry's in particular). As Terry points out, there is a second half to the problem: how to dispatch arbitrary messages?
To make it more concrete, I should explain that I'm dealing with Windows window messages (e.g. WM_CREATE, WM_SETTEXT etc.) which are unsigned ints. I dispatch these to handlers with the signature:
LRESULT on(message
m); LRESULT on(message m); ..and so on. 'message' is defined like this:
template<unsigned int Id> class message; // intentionally undefined
template<> class message
{ ... } template<> class message { ... } So there is in fact a list of 'PossibleMessages' available to the compiler. It is every argument to a specialisation of class message<Id>. Is there a way I can harvest these to build the PossibleMessages list?
Thanks again.
Alex

On Fri, 21 May 2010 17:13:43 -0500, Terry Golubiewski wrote:
Another thing to consider is that using a single type-list with over 100 message types will significantly (to me) slow compile time and may approach compiler limits.
I was worrying about this.
You can avoid these limits by grouping messages into related groups or by using a dynamic dispatcher that registers callbacks at runtime initialization.
My 'widgets' will be organised in a class heirarchy. I supposed I can use a separate list for each subclass. The dispatcher can first try the widget class's list and then its base class's list and so on. This should keep the size of any individual list under 20. Alex

On Sat, 22 May 2010 00:34:04 +0100, Alexander Lamaison wrote:
My 'widgets' will be organised in a class heirarchy. I supposed I can use a separate list for each subclass. The dispatcher can first try the widget class's list and then its base class's list and so on. This should keep the size of any individual list under 20.
Though this makes no sense if I actually succeed in auto-dispatching the messages as I'll have to have a big list of possible messages. Hmmmm, perhaps I should just stick with what I've got. Alex

Another thing to consider is that using a single type-list with over 100 message types will significantly (to me) slow compile time and may approach compiler limits.
I was worrying about this.
See Appendix C of "C++ Template Metaprogramming" by Abrahams and Gurtovoy. Choosing the proper MPL collection can make the difference. None of the effects mentioned in the chapter shows a wall near N=100. --John TradeStation Group, Inc. is a publicly-traded holding company (NASDAQ GS: TRAD) of three operating subsidiaries, TradeStation Securities, Inc. (Member NYSE, FINRA, SIPC and NFA), TradeStation Technologies, Inc., a trading software and subscription company, and TradeStation Europe Limited, a United Kingdom, FSA-authorized introducing brokerage firm. None of these companies provides trading or investment advice, recommendations or endorsements of any kind. The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

Zitat von Alexander Lamaison
I would like to dispatch messages to a class based simply on the *presence* of a message handler method.
Currently, the classes maintain an MPL vector of the messages they handle and must implement a on(message
) method for each one. The dispatcher uses this compile-time list to build the dispatching code. This means the information is maintained twice and may fall out of sync (e.g. adding the handler but forgetting to update the message vector. Are there any template metaprogramming tricks I can employ to dispatch the message to a handler method if it exists and the default handler otherwise? All this information is available at compile time. The question is are templates are powerful enough to make use of it?
templates are not, and there is no portable way to detect the presence
of a member function.
you can however use ADL for this type of thing, if you don't need the
information whether the message handler is present for anything other
than calling it:
class A{
friend void message(A &this_,message msg){
...
}
};
namespace detail{
template

I've attached a working (on Visual C++ 2008) example.
terry
----- Original Message -----
From: "Alexander Lamaison"
I would like to dispatch messages to a class based simply on the *presence* of a message handler method.
Currently, the classes maintain an MPL vector of the messages they handle and must implement a on(message
) method for each one. The dispatcher uses this compile-time list to build the dispatching code. This means the information is maintained twice and may fall out of sync (e.g. adding the handler but forgetting to update the message vector. Are there any template metaprogramming tricks I can employ to dispatch the message to a handler method if it exists and the default handler otherwise? All this information is available at compile time. The question is are templates are powerful enough to make use of it?
Many thanks.
Alex
participants (7)
-
Alexander Lamaison
-
Joel Falcou
-
John Dlugosz
-
Kim Kuen Tang
-
Steven Watanabe
-
strasser@uni-bremen.de
-
Terry Golubiewski