Warum ist set :: find keine Vorlage?
Mit Template-Funktionen von<algorithm>
Sie können solche Dinge tun
struct foo
{
int bar, baz;
};
struct bar_less
{
// compare foo with foo
bool operator()(const foo& lh, const foo& rh) const
{
return lh.bar < rh.bar;
}
template<typename T> // compare some T with foo
bool operator()(T lh, const foo& rh) const
{
return lh < rh.bar;
}
template<typename T> // compare foo with some T
bool operator()(const foo& lh, T rh) const
{
return lh.bar < rh;
}
};
int main()
{
foo foos[] = { {1, 2}, {2, 3}, {4, 5} };
bar_less cmp;
int bar_value = 2;
// find element {2, 3} using an int
auto it = std::lower_bound(begin(foos), end(foos), bar_value, cmp);
std::cout << it->baz;
}
Imstd::set
Methoden wiefind
Sie müssen ein Objekt vom Typ übergebenset::key_type
Das zwingt Sie oft, ein Dummy-Objekt zu erstellen.
set<foo> foos;
foo search_dummy = {2,3}; // don't need a full foo object;
auto it = foos.find(search_dummy);
Es wäre so hilfreich, wenn man eben anrufen kannfoos.find(2)
. Gibt es einen Grund dafür?find
Es kann keine Vorlage sein, die alles akzeptiert, was an das weniger wichtige Prädikat übergeben werden kann. Und wenn es nur fehlt, warum ist es nicht in C ++ 11 (glaube ich nicht).
Die Hauptfrage ist, WARUM es nicht möglich ist und wenn es möglich ist, WARUM der Standard beschlossen hat, es nicht bereitzustellen. Als zweite Frage kannst du Workarounds vorschlagen :-) (boost::multi_index_container
fällt mir gerade ein, was eine Schlüsselextraktion aus Werttypen bietet)
Ein weiteres Beispiel mit einem teurer zu konstruierenden Wertetyp. Der Schlüsselname
ist Teil des Typs und sollte nicht als Kopie in Maps Key verwendet werden.
struct Person
{
std::string name;
std::string adress;
std::string phone, email, fax, stackoferflowNickname;
int age;
std::vector<Person*> friends;
std::vector<Relation> relations;
};
struct PersonOrder
{
// assume that the full name is an unique identifier
bool operator()(const Person& lh, const Person& rh) const
{
return lh.name < rh.name;
}
};
class PersonRepository
{
public:
const Person& FindPerson(const std::string& name) const
{
Person searchDummy; // ouch
searchDummy.name = name;
return FindPerson(searchDummy);
}
const Person& FindPerson(const Person& person) const;
private:
std::set<Person, PersonOrder> persons_;
// what i want to avoid
// std::map<std::string, Person> persons_;
// Person searchDummyForReuseButNotThreadSafe;
};