Boost logo

Boost Users :

Subject: [Boost-users] How to write a predicate for mpl::find_if that is able to work with placeholders?
From: Michael Schulze (mschulze_at_[hidden])
Date: 2010-09-18 14:43:04


Hi list,

I have a problem that bothers me since days. It seems, that I am always
doing something wrong. I try to write a meta function, that is able to
work with placeholders and is applicable to mpl::find_if. I understand
the example from the documentation where is_same is used, which is in my
understanding also a meta function. is_same gets always the current
element of the sequence and compares it with the type given as second
template argument to itself. Correct me if I am wrong at this point.

So far so good, what I need is not the comparison to the type but
instead a comparison with an encapsulated type, a kind of tag type if
you want. Here is my class template

template<int i>
struct Slot {
    typedef Slot type;
    typedef int_<i> slot_id;
};

and I would like to test whether a certain slot_id is contained within a
sequence, because the Slot class template may have different further
template arguments, here omitted for the sake of clarity.

My created meta function is:

template<typename A, typename B>
struct contained : is_same< typename A::slot_id ,B> {};

A possible sequence may be defined as:

typedef vector<Slot<0>, Slot<10>, Slot<15> > slots;

and the find_if's invocation should look like this

typedef find_if<slots, contained< _1, int_<10> > >::type t10;

and a comparison with the dereferenced returned iterator should give true

BOOST_MPL_ASSERT(( is_same< deref<t10>::type, Slot<10> > ));

However, until now I have not much luck with my different tries because
I get always compile errors that state that the mpl::arg<1> did not has
slot_id type. This is totally right, however, how I reach it that not
the placeholder is given to the meta function but instead the current
element of the sequence to which the iterator points and for which the
placeholder is a substitute. If I reflect it seems I have not fully
understand how the placeholder mechanism works in detail but I would
like to get it.

Okey, I have two solution that work and give me the correct result for
my problem. I created two different "contained" definitions and find_if
invocations

1. version:

template<typename Nr>
struct contained1 {
   template <typename Slot>
   struct apply : ::boost::is_same< typename Slot::slot_id, Nr > {};
};

typedef find_if<slots, contained1<int_<10> > >::type t11;

2. version:

struct contained2 {
template<typename A, typename B>
    struct apply : is_same< typename A::slot_id,B>::type {};
};

typedef find_if<slots, bind< contained2, _1, int_<10> > >::type t12;

Both versions work, because they are meta function classes, but the
invocation of find_if and how the parameter is delivered to the
predicate is not clear at least in the first version. In the second
version this is clear but we need an additional bind.

Is there a way, to get my initial version working, and to use a meta
function instead of a meta function class. In my eyes, my initial
find_if invocation is clearer and more readable e.g. for maintainers.

Thanks and regards
Michael


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