Prädikate - STL Container
-
Hallo,
ich schalge mich mal wieder mit den STL Containern rum. Ich möchte eine Wrapper Classe um eine map schreiben, die eine Menge von Instanzen aus der Map auf einmal (in einem Vector) zurückgeben kann. Die auskommentierte Funktion get_instances_with_b() hat auch schon so funktioniert wie ich das haben wollte. Nun möchte ich allerdings eine Selektion mit übergeben. Ich dachte eigentlich, dass ich nur das Prädikat (Is_B) um einen zweiten Operator erweitern müsste, bekomme dann aber den Compiler ums verrecken nicht dazu, dass er meinen Code übersetzt.

Was mache ich falsch?
Ist es eigentlich ok ein Vector mit Pointern zurückzugeben, oder ist das ehr gefährlich/zu vermeiden?
Danke schon mal für eure Antworten,
Christian
#include <iostream> #include <map> #include <vector> #include <string> #include <functional> class Instance { public: enum Enum_T { A, B, C }; Instance() : _key(0), _selection(A) { }; Instance(int key, Enum_T selection) : _key(key), _selection(selection) { }; virtual ~Instance() { }; int get_key() const { return _key; }; Enum_T get_selection() const { return _selection; }; private: int _key; Enum_T _selection; }; class MyMap { public: MyMap() { }; virtual ~MyMap() { }; void insert (const Instance& i) { _map[i.get_key()] = i; }; void erase(const int key) { _map.erase(key); }; /* const std::vector<const Instance*> get_instances_with_b() { std::vector<const Instance*> result; Map_T::iterator sit = _map.begin(); while ((sit = find_if(sit, _map.end(), Is_B())) != _map.end()) { result.push_back(&(sit->second)); sit++; } return result; } */ const std::vector<const Instance*> get_instances_with(Instance::Enum_T selection) { Map_T::const_iterator iterator = find_if(_map.begin(), _map.end(), std::bind2nd(Is_B(), selection)); Map_T::iterator sit = _map.begin(); while ((sit = find_if(sit, _map.end(), Is_B())) != _map.end()) { result.push_back(&(sit->second)); sit++; } return result; } private: typedef std::map<int, Instance> Map_T; class Is_B { public: bool operator()(const Map_T::value_type& i, const Instance::Enum_T& s) const { if (i.second.get_selection() == s) return true; return false; } }; Map_T _map; }; int main() { MyMap mymap; mymap.insert(Instance(1, Instance::A)); mymap.insert(Instance(2, Instance::B)); mymap.insert(Instance(3, Instance::B)); mymap.insert(Instance(4, Instance::A)); mymap.insert(Instance(5, Instance::B)); mymap.insert(Instance(6, Instance::C)); /* std::vector<const Instance*> v = mymap.get_instances_with_b(); for (int i = 0; i < v.size(); i++) { std::cout << "Instance(" << v[i]->get_key() << ", " << v[i]->get_selection() << ")" << std::endl; } */ }
-
Hallo,
es gibt eine Menge Varianten:
- Dein Functor sollte von
std::binary_function<Map_T::value_type, Instance::Enum_T, bool>geerbt sein. Dann sollte alles funktionieren wie du willst.
- Einfache Schleife:
const std::vector<const Instance*> get_instances_with(Instance::Enum_T selection) { std::vector<const Instance*> result; Map_T::iterator sit = _map.begin(), end = _map.end(); while(sit != end) { if(sit->second.get_selection() == selection) result.push_back(&(sit->second)); ++sit; } return result; }- Leider gibt's std::copy_if im Standart nicht
Ist aber sehr einfach zu implementieren 
template<typename ForwardIter, typename OutputIter, typename UnaryPred> OutputIter copy_if(ForwardIter begin, ForwardIter end, OutputIter dest, UnaryPred f) { while(begin != end) { if(f(*begin)) *dest++ = *begin; ++begin; } }dann sieht deine methode so aus:
copy_if(_map.begin(), _map.end(), std::back_insert_iterator(_map), XXXX);XXXX ist deine Hausaufgabe

-
ssm schrieb:
- Leider gibt's std::copy_if im stan**** nicht
Ist aber sehr einfach zu implementieren 
hab ich auch mal gedacht. bis mir aufgefallen ist, dass das nichts weiter als remove_copy_if mit invertiertem prädikat (z.b. per std::unary_negate) ist. der algorithmus fehlt also nicht wirklich.
- Leider gibt's std::copy_if im stan**** nicht
-
camper schrieb:
remove_copy_if mit invertiertem prädikat
Hast du recht
ich dachte damit löscht man was(von remove). Wie ich sehe, macht dieses Algorithmus genau das Richtige!
Also für alle, die wie ich nicht wussten:Remove_copy_if copies elements from the range [first, last) to a range beginning at result, except that elements for which pred is true are not copied.