[Gelöst] Wie Prädikat formulieren bei boost::mpl::find_if mit placeholdern?
-
Hallo Forum,
möchte ein Prädikat für den Einsatz in boost::mpl::find_if programmieren, bei dem auch ein Parameter mit einem placeholdern gesetzt wird, wie hier z.B.
typedef vector<char,int,unsigned,long,unsigned long> types; typedef find_if<types, is_same<_1,unsigned> >::type iter; BOOST_MPL_ASSERT(( is_same< deref<iter>::type, unsigned > ));Jetzt will ich aber nicht auf den Typ vergleichen, der im Vector direkt zugreifbar ist, sondern auf einen eingekapselten Typ.
template<int i> struct Slot { typedef Slot type; typedef int_<i> hold_type; }; typedef vector<Slot<0>, Slot<10>, Slot<15> > slots; typedef find_if<slots, equal< _1, int_<10> > >::type t10; BOOST_MPL_ASSERT(( is_same< deref<t10>::type, Slot<10> > ));Die Frage ist nun, wie ich dieses "equal" zu programmieren habe. Ich mache scheinbar immer irgend etwas falsch.
Wenn ich statt des "equal< _1, int_<10> >" auf "equal<int_<10> >" umschreibe, wobei dieses dann eine Metafunktionsklasse ist und sie so implementiere
template<typename Nr> struct equal { template <typename Slot> struct apply : ::boost::is_same< typename Slot::hold_type, Nr > {}; };, funktioniert es wie es soll.
Ich würde es aber halt auch gern mal mit placeholdern hinbekommen und diese damit richtig verstehen. Gelingt mir aber nicht. Ich hoffe einer von euch C++-Gurus kann mir da weiter helfen.
Danke und Gruß
-
Hat denn wirklich keiner weiter eine Idee wie man dieses anstellen könnte?
Was ich jetzt versuchte habe ist folgendes:
struct equal2 { template<typename A, typename B> struct apply : is_same< typename A::hold_type,B>::type {}; }; typedef vector<Slot<0>, Slot<10>, Slot<15> > slots; typedef find_if<slots, bind< equal2, _1, int_<10> > >::type t10; BOOST_MPL_ASSERT(( is_same< deref<t10>::type, Slot<10> > ));Dieses funktioniert, aber der placeholder ist halt nicht direkt ein Argument wie beim Standardbeispiel von find_if. Die Bindung des placeholders arbeitet jetzt über bind und damit wird dann mein equal2 richtig mit dem Argument der Sequence anstatt dem placeholder aufgerufen. Wie ich es aber direkt hinbekomme, habe ich leider keinen Plan. Außerdem ist equal2 auch eine Metafunktionsklasse und ich würde es auch gern mit einer einfachen Metafunktion hinbekommen. So wie bei is_same aus meinem ersten Posting beispielsweise.
Irgendwelche Hinweise, was man da machen könnte oder wo der Hacken ist an meinem Vorgehen.
Gruß
-
Hi Forum,
ich habe es hin bekommen
Nachdem ich mir den Quelltext von MPL etwas genauer angesehen habe, weiß ich wie es funktioniert und damit der Thread als gelöst gekennzeichnet werden kann, will ich mal den Weg aufzeigen, wie solch ein Prädikat aussehen muss. Hier ist der Quelltext des Prädikatestemplate<typename A, typename B> struct equal { static const int value=is_same<typename A::slot_id, B>::value; };Eigentlich ja einfach, aber muss man erst einmal drauf kommen, warum es so geht und der/die anderen Weg nicht funktioniert haben. Ok die Erklärung:
Es handelt sich also um eine Metafunktion und der entscheidende Punkt war die Definition des value. Ich hatte unter anderem auch versucht direkt von is_same zu erben, wodurch der value von is_same kommt. Aber: Bei der Instantiierung von equal wurde dann auch is_same direkt instantiiert und auf den eingekapselten Typ zugegriffen, der bei einem Placeholder nicht existiert. Wenn ich die Definition des value aber in equal reinschreibe, wird dieser Ausdruck erst ausgewertet, wenn auf value zugegriffen wird. Dies geschieht in einem Kontext, wo der Placeholder durch das aktuelle Element der Sequenz ersetzt wird. Dieser Typ hat den eingekapselten Type slot_id und diesen kann ich dann vergleichen.Und hier der restliche Quelltext, um zu zeigen wie equal jetzt benutzt werden kann.
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, equal< _1, int_<10> > >::type t10; BOOST_MPL_ASSERT(( is_same< deref<t10>::type, Slot<10> > ));Jetzt arbeitet alles so, wie es soll
