Der Grund, warum sie dies hart gemacht haben, ist, weil es gefährlich ist. Sie müssen GARANTIEREN, dass keiner der std::string
Mitglieder, von denen ein Schlüssel abgezogen wird, niemals den Wert ändert oder die gesamte Karte ungültig wird. Interessant, die erste Lösung, die in den Sinn kommt, erscheint wahnsinnig hackish, und sieht wie UB, aber ich glaube, dass ich sehr vorsichtig die UB.
struct key_type {
mutable const char* ptr;
};
bool operator<(const key_type& lhs, const key_type& rhs)
{return strcmp(lhs.ptr, rhs.ptr)<0;}
struct person {
std::string name;
int age;
};
person& people_map_get(std::map<key_type, person>& map, const char* name) {
auto it = map.insert(name, person{name}).first; //grab, possibly insert
if->first.ptr = it->second.name.c_str(); //in case of insert, fix ptr
return it->second;
}
person& people_map_assign(std::map<key_type, person>& map, person p) {
auto pair = map.insert(name, p); //grab, possibly insert
auto it = pair.first;
if (pair.second == false)
it->second = std::move(p);
if->first.ptr = it->second.name.c_str(); //ptr probably invalidated, so update it
return it->second;
}
int main() {
std::map<key_type, person> people;
people_map_assign(people, person{"ted"});
person frank = people_map_get(people, "frank");
}
Wie ich hoffe, ist klar, das ist verrückt der Nähe von UB und sehr viel nicht zu empfehlen. Während eines Einfüge-/Suchvorgangs zeigt der Schlüssel auf das temporäre Objekt oder die Eingabezeichenfolge, und sobald das Objekt eingefügt/gefunden wird, wird der Schlüssel so geändert, dass er auf den im Zeichenfolgenelement enthaltenen Wert zeigt, und solange Sie tun nie etwas, das würde den Rückgabewert von .c_str()
auf jedem enthaltenen person
Objekt ungültig machen, alles funktioniert nur knapp. Ich denke.
Wie wäre es mit einem 'std :: set' wo 'C' die in' T' gespeicherte Zeichenkette vergleicht? –
@Daniel: Aber dann müsste ich ein ganzes 'T'-Objekt für die Suche bereitstellen, und nicht nur eine' std :: string', oder? Oder kann "C" überladen werden, um "T" mit "T" und auch "T" mit "std :: string" zu vergleichen? –
Ahh, ich sehe, dass C++ 14 ein Template-'find'-Member hinzufügen wird, um nach jedem Typ zu suchen, der mit' T' verglichen werden kann. –