How to write a predicate for mpl::find_if that is able to work with placeholders?

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

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I solved it. I crawled through the mpl sources (not an easy task) and found how it has to work. The predicate needs to be defined as: template<typename A, typename B> struct contained { static const int value=is_same<typename A::slot_id, B>::value; template<typename T1, typename T2> struct apply; };
template<int i> struct Slot { typedef Slot type; typedef int_<i> slot_id; }; typedef vector<Slot<0>, Slot<10>, Slot<15> > slots; typedef find_if<slots, contained< _1, int_<10> > >::type t10; BOOST_MPL_ASSERT(( is_same< deref<t10>::type, Slot<10> > ));
This works as intended. However, finding out how to write such a predicate, was very hard. Providing examples, describing the different kinds of predicates and how they need to be written in order to work with placeholders, would be very helpful. Maybe such things could be added to the mpl documentation, because I am sure, I am not the first that came up with such an issue. Regards, Michael -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJMmP6eAAoJEKn9/33w5fU9FQAH/0gzuptHEBfAqfkVrmjD3/+X ibhtkSMCyXarkTSbTLYeJ7mOZ7cZ9hMpa2pLvQG0W6jLFvyjVnL+zJDrIbNFDFs9 ++nIzlijFqnaVSqi8WRAw5mXn9Ai2j0NFRyBDz70N+fPFkm+KsRDyL6pME6oLI+u WDRG4jexnLeomrIePrWbTdpNQaTKerp91cnR/6wJdMNBgDxePnP9Yzye5ltPsJzi H7SpqqHpX9yXxslvMi7vN7V8qrPwHx1Y17ILzIP77/EA/hBpFkcxPC8H8YdoUF9n UxIJ5RGwq54bEgF8qvVKkZsZy8s5u42H3E+rbNxmUcoQmaQ+Ow7gvEzQqVJTbHI= =siFh -----END PGP SIGNATURE-----

I solved it. I crawled through the mpl sources (not an easy task) and found how it has to work.
The predicate needs to be defined as:
template<typename A, typename B> struct contained { static const int value=is_same<typename A::slot_id, B>::value; template<typename T1, typename T2> struct apply; }; I tested again and I realized that the nested apply may be omitted and it works also as it should.
template<int i> struct Slot { typedef Slot type; typedef int_<i> slot_id; }; typedef vector<Slot<0>, Slot<10>, Slot<15> > slots; typedef find_if<slots, contained< _1, int_<10> > >::type t10; BOOST_MPL_ASSERT(( is_same< deref<t10>::type, Slot<10> > ));
This works as intended. However, finding out how to write such a predicate, was very hard. Providing examples, describing the different kinds of predicates and how they need to be written in order to work with placeholders, would be very helpful. Maybe such things could be added to the mpl documentation, because I am sure, I am not the first that came up with such an issue.
Regards, Michael
participants (1)
-
Michael Schulze