[MPL] searching a vector at runtime

I'm trying to recursively traverse an MPL vector_c but I'm not sure what the base-case type should be. I want to pick a type from a mpl::vector at runtime and use it to dispatch a call to an overloaded function. Basically tag-dispatch with the tags being looked up in an MPL collection. The runtime value is an unsigned it so I just store unsigned ints in a vector_c. Then I want to traverse this vector and compare each item to the runtime value. If I find a match, I want to use it to call an overloaded function. Here's how I'm trying to do it so far: template<typename ID> class message { ... } template<typename Sequence> // MAP is a vector_c struct dispatcher { template<typename T> static result dispatch(T* obj, unsigned int message_id, int arg) { typedef boost::mpl::front<Sequence>::type head; typedef boost::mpl::pop_front<Sequence>::type tail; if (head::value == message_id) return obj->handle(messagehead::value, arg); else return dispatcher<tail>::dispatch(obj, message_id, arg); } }; template<> struct dispatcherboost::mpl::void_ // WHAT SHOULD THIS TYPE BE? { template<typename T> static result dispatch(T* obj, unsigned int message_id, int arg) { return obj->default_message_handler(message_id, arg); } }; struct handler { result handle(message<MESSAGE1>) { /* do stuff 1 */ } result handle(message<MESSAGE2>) { /* do stuff 2 */ } result default_message_handler(unsigned int id, int arg) {} } I'm stuck on what to make the dispatcher base case which is reached when pop_front is called on a list with one item. At first I though the resulting type was void_ but apparently this doesn't match. I'm new to MPL. Can someone explain what I'm doing wrong here or if there's an altogether better way? Many thanks. Alex Lamaison

Zitat von Alexander Lamaison
I'm trying to recursively traverse an MPL vector_c but I'm not sure what the base-case type should be.
template<typename Sequence> // MAP is a vector_c struct dispatcher { template<typename T> static result dispatch(T* obj, unsigned int message_id, int arg) { typedef boost::mpl::front<Sequence>::type head; typedef boost::mpl::pop_front<Sequence>::type tail;
if (head::value == message_id) return obj->handle(messagehead::value, arg); else return dispatcher<tail>::dispatch(obj, message_id, arg); } };
template<> struct dispatcherboost::mpl::void_ // WHAT SHOULD THIS TYPE BE? { template<typename T> static result dispatch(T* obj, unsigned int message_id, int arg) { return obj->default_message_handler(message_id, arg); } };
I'm stuck on what to make the dispatcher base case which is reached when pop_front is called on a list with one item. At first I though the resulting type was void_ but apparently this doesn't match.
I'm new to MPL. Can someone explain what I'm doing wrong here or if there's an altogether better way?
if you encounter this type of thing regularily, you might want to have
a look at Boost.Fusion, which has runtime algorithms that can also be
used on Boost.MPL sequences.
however, using function templates is much simpler than the dispatch
class specialization you attempted above:
template

On Sun, 16 May 2010 09:07:53 +0200, strasser@uni-bremen.de wrote:
Zitat von Alexander Lamaison
: I'm trying to recursively traverse an MPL vector_c but I'm not sure what the base-case type should be.
if you encounter this type of thing regularily, you might want to have a look at Boost.Fusion, which has runtime algorithms that can also be used on Boost.MPL sequences. however, using function templates is much simpler than the dispatch class specialization you attempted above:
template
void dispatch(int id,mpl::true_ endofvec){} template
void dispatch(int id,mpl::false_){ if(id == mpl::deref<It>::type::value){ ... }else{ typedef typename mpl::next<It>::type Next; dispatch (id,typename is_same ::type()); } } call with mpl::begin<YourVec> and mpl::end<YourVec> as template arguments
Thanks! This does exactly what I want. Just out of interest, how would Boost.Fusion help here. I had a look at its algorithms but they seem to require an instantiated sequence. For instance the signature of find() is: template< typename T, typename Sequence > unspecified find(Sequence& seq); I need the result of my search to be a type rather than a value. The Fusion examples seem to return values. Many thanks. Alex

Zitat von Alexander Lamaison
template
void dispatch(int id,mpl::true_ endofvec){} template
void dispatch(int id,mpl::false_){ if(id == mpl::deref<It>::type::value){ ... }else{ typedef typename mpl::next<It>::type Next; dispatch (id,typename is_same ::type()); } } call with mpl::begin<YourVec> and mpl::end<YourVec> as template arguments
Thanks! This does exactly what I want. Just out of interest, how would Boost.Fusion help here. I had a look at its algorithms but they seem to require an instantiated sequence. For instance the signature of find() is:
template< typename T, typename Sequence > unspecified find(Sequence& seq);
I need the result of my search to be a type rather than a value. The Fusion examples seem to return values.
there is no difference between type and value with MPL sequences. e.g. the element type of a vector_c is mpl::int_<5>, which evaluates to 5. MPL sequences are empty objects, so they can be instantiated. but you're right that fusion::find(_if) doesn't seem to be suitable for your case, as it doesn't take a (runtime) functor, only a (compiletime) predicate. but I've used fusion::fold before with MPL sequences.
participants (2)
-
Alexander Lamaison
-
strasser@uni-bremen.de