Boost logo

Boost Users :

Subject: Re: [Boost-users] Auto dispatch metaprogramming tricks
From: Kim Kuen Tang (kuentang_at_[hidden])
Date: 2010-05-21 10:13:08


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<MESSAGE_ID>) 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<typename U, typename U::size_type
(U::*)() const>
                      struct SFINAE {};
                      typedef char yes_type;
                      typedef char(&no_type)[2];
                      template<typename U>
                      static no_type test_HasSizeMethod(...);
                      template<typename U>
                      static yes_type
test_HasSizeMethod(SFINAE<U,&U::size>*);
                 public:
                      typedef bool value_type;
                      BOOST_STATIC_CONSTANT(value_type
                           , value = sizeof(yes_type) ==
sizeof(test_HasSizeMethod<T>(0) ) );
                      typedef mpl::bool_<value> type;
            };

> 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<class T, class M>
> 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 <boost/cstdlib.hpp>
# include <boost/mpl/int.hpp>
# include <boost/mpl/assert.hpp>

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<class T, class M>
struct has_on : boost::mpl::bool_<
   sizeof(check_on_result(((has_on_impl<T>*)0)->on(*((M*)0)) , 0)) !=
sizeof(no)
> {};

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<has_on_struct,int> ));
    return boost::exit_success;
}

There is also a more generic working example in the ticket. See

https://svn.boost.org/trac/boost/ticket/3783

> In Christ,
> Steven Watanabe
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net