Gelöst: STL not?
-
Hallo!
Mein Problem: Ich will das Prädikat, was ich in std::find_if benutze, negieren. Das unäre Prädikat wird durch ein spezielles bind2nd() kreiert, hinter der eine spezielle unary_function steht. Sieht in etwa so aus:template <typename Cmp = std::greater_equal> class widget { private: template <typename BinOp> class tree_binder2nd : public std::unary_function<typename BinOp::first_argument_type, typename BinOp::result_type> { private: BinOp op; typename BinOp::second_argument_type arg2; public: tree_binder2nd(const BinOp& x, const typename BinOp::second_argument_type& v) : op(x), arg2(v) { } typename BinOp::result_type operator() (const std::pair<key_t, payload_t>* x) const { return op(x->first, arg2); } }; template <typename BinOp, typename T> tree_binder2nd<BinOp> bind2nd(const BinOp& op, const T& arg2) const { return tree_binder2nd<BinOp>(op, arg2); } // später, in irgendeiner Memberfunktion iterator = std::find_if(container.begin(), container.end(), bind2nd(Cmp(), *iterator)); // wie mach ich das negativ? };Meine Versuche, irgendwas mit std::not1() hin zu biegen, scheiterten. Wie man vielleicht sieht, handelt es sich hierbei um einen Container mit std::pair als Inhalt. Der operator() soll also den umgekehrten Wert zurückliefern. Bloß wie?

-
template <typename Cmp = std::greater_equal>greater_equal ist selbst ein template.
Ansonsten sollte not1 schon das richtige tun.
-
Hm... Ein Fehler ist mir schon unterlaufen. Eigentlich müsste es ja so lauten:
iterator = std::find_if(container.begin(), container.end(), bind2nd(Cmp(), iterator->first));Das kompiliert wunderbar. Sobald ich ein not1() davor setze:
iterator = std::find_if(container.begin(), container.end(), std::not1(bind2nd(Cmp(), iterator->first)));fängt es an zu hageln:
error C2664: 'bool std::unary_negate<_Fn1>::operator ()(const std::basic_string<_Elem,_Traits,_Ax> &) const': Konvertierung des Parameters 1 von 'std::pair<_Ty1,_Ty2>' in 'const std::basic_string<_Elem,_Traits,_Ax> &' nicht möglichHm...? Ich will einfach nur immer die firsts von pairs in einer std::list mit einem statischen first mittels compare_t vergleichen. Der first-Typ ist hier std::string.
Bzgl. dem Template:
Jap, hab ich nur so lapidar geschrieben, im echten Code ist der Parameter natürlich vorhanden.
-
Was für ein Typ hat denn greater_equal für das erste Argument bei dir?
-
std::string
-
Da bin ich jetzt durch einen Gedankenblitz draufgekommen:
iterator = std::find_if(container.begin(), container.end(), bind2nd(std::not2(Cmp()), iterator->first)));Ich will ja nicht das gesamte Ergebnis negieren, sondern nur das binäre Prädikat zum Vergleichen. *patsch*
Ist C++ eigentlich immer so kompliziert? Oder mache ich was falsch? Das Beispiel hier war noch vereinfacht, eigentlich zeigt der Iterator auf einen Zeiger (noch eine Derefernzierung drauf). Das will ich meinem Info-Lehrer nur ungern antun:iter = std::find_if(payload.begin(), payload.end(), bind2nd(std::not2(compare_t()), (*half)->first));
-
template <typename BinOp> class tree_binder2nd : public std::unary_function<[b]typename BinOp::first_argument_type[/b], typename BinOp::result_type> { private: BinOp op; typename BinOp::second_argument_type arg2; public: tree_binder2nd(const BinOp& x, const typename BinOp::second_argument_type& v) : op(x), arg2(v) { } typename BinOp::result_type operator() ([b]const std::pair<key_t, payload_t>*[/b] x) const { return op(x->first, arg2); } };Hier passt etwas nicht zusammen.
-
Ad aCTa schrieb:
Ist C++ eigentlich immer so kompliziert? Oder mache ich was falsch? Das Beispiel hier war noch vereinfacht, eigentlich zeigt der Iterator auf einen Zeiger (noch eine Derefernzierung drauf). Das will ich meinem Info-Lehrer nur ungern antun:
iter = std::find_if(payload.begin(), payload.end(), bind2nd(std::not2(compare_t()), (*half)->first));Eine Alternative wäre:
iter = std::find_if(payload.begin(), payload.end(), !std::tr1::bind(compare_t(), _1, (*half)->first));Ob das wirklich schöner aussieht, ist wiederum eine andere Frage. Aber das sind halt die Tücken des funktionalen STL-Stils. Wenn der Code auch für weniger Erfahrene leicht verständlich sein soll, schreibst du eben eine Schleife. Oder eine separate Funktion respektive einen Funktor, den du dann direkt an
find_if()übergeben kannst:iter = std::find_if(payload.begin(), payload.end(), &my_function);