
Unbekannt
Ich frage mich, warum ich STL-Maps nicht mit benutzerdefinierten Klassen verwenden kann. Wenn ich den folgenden Code kompiliere, erhalte ich die folgende kryptische Fehlermeldung. Was heißt das? Warum passiert es auch nur mit benutzerdefinierten Typen? (Primitive Typen sind in Ordnung, wenn sie als Schlüssel verwendet werden.)
C:\MinGW\bin..\lib\gcc\mingw32\3.4.5……..\include\c++\3.4.5\bits\stl_function.h||In Mitgliedsfunktion `bool std:: less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp =
Class1]’:|
C:\MinGW\bin..\lib\gcc\mingw32\3.4.5……..\include\c++\3.4.5\bits\stl_map.h|338|instanziiert von `_Tp& std:: map<_Key, _Tp, _Compare, _Alloc>::Operator[](const _Key&) [with _Key = Class1, _Tp = int, _Compare = std::less, _Alloc = std::allocator >]’|
C:\Benutzer\Admin\Dokumente\dev\sandbox\sandbox\sandbox.cpp|24|von hier aus instanziiert|
C:\MinGW\bin..\lib\gcc\mingw32\3.4.5……..\include\c++\3.4.5\bits\stl_function.h|227|error: no match for ‘operator <' in '__x < __y'| ||=== Bau abgeschlossen: 1 Fehler, 0 Warnungen ===|
#include <iostream>
#include <map>
using namespace std;
class Class1
{
public:
Class1(int id);
private:
int id;
};
Class1::Class1(int id): id(id)
{}
int main()
{
Class1 c1(1);
map< Class1 , int> c2int;
c2int[c1] = 12;
return 0;
}

Pavel Minaev
Du nicht verfügen über definieren operator<
eigentlich für deine Klasse. Sie können auch eine Komparatorfunktionsobjektklasse dafür erstellen und diese zum Spezialisieren verwenden std::map
. Um dein Beispiel zu erweitern:
struct Class1Compare
{
bool operator() (const Class1& lhs, const Class1& rhs) const
{
return lhs.id < rhs.id;
}
};
std::map<Class1, int, Class1Compare> c2int;
Es passiert einfach so, dass die Voreinstellung für den dritten Template-Parameter von std::map
ist std::less
die an delegieren wird operator<
für Ihre Klasse definiert (und schlagen fehl, wenn es keine gibt). Aber manchmal möchten Sie, dass Objekte als Kartenschlüssel verwendet werden können, aber Sie haben eigentlich keine sinnvoll Vergleichssemantik, und deshalb möchten Sie die Leute nicht verwirren, indem Sie angeben operator<
in deiner Klasse nur dafür. Wenn das der Fall ist, können Sie den obigen Trick anwenden.
Eine weitere Möglichkeit, dasselbe zu erreichen, ist die Spezialisierung std::less
:
namespace std
{
template<> struct less<Class1>
{
bool operator() (const Class1& lhs, const Class1& rhs) const
{
return lhs.id < rhs.id;
}
};
}
Das hat den Vorteil, dass es abgeholt wird std::map
“standardmäßig”, und doch belichten Sie nicht operator<
andernfalls zum Client-Code.

GManNickG
Standardmäßig std::map
(und std::set
) verwenden operator<
Sortierung zu bestimmen. Daher müssen Sie definieren operator<
auf deine Klasse.
Es werden zwei Objekte betrachtet gleichwertig if !(a < b) && !(b < a)
.
Wenn Sie aus irgendeinem Grund einen anderen Komparator verwenden möchten, wird das dritte Vorlagenargument der map
kann geändert werden, zu std::greater
zum Beispiel.

aJ.
Sie müssen definieren operator <
für die Klasse1.
Map muss die Werte mit dem Operator < vergleichen und daher müssen Sie dasselbe angeben, wenn benutzerdefinierte Klassen als Schlüssel verwendet werden.
class Class1
{
public:
Class1(int id);
bool operator <(const Class1& rhs) const
{
return id < rhs.id;
}
private:
int id;
};

Kaushal
class key
{
int m_value;
public:
bool operator<(const key& src)const
{
return (this->m_value < src.m_value);
}
};
int main()
{
key key1;
key key2;
map<key,int> mymap;
mymap.insert(pair<key,int>(key1,100));
mymap.insert(pair<key,int>(key2,200));
map<key,int>::iterator iter=mymap.begin();
for(;iter!=mymap.end();++iter)
{
cout<<iter->second<<endl;
}
}
Schlüssel müssen vergleichbar sein, aber Sie haben keinen passenden definiert operator<
für Ihre benutzerdefinierte Klasse.
Ich möchte ein wenig erweitern Pavel Minaevs Antwort, die Sie lesen sollten, bevor Sie meine Antwort lesen. Beide von Pavel vorgestellten Lösungen werden nicht kompiliert, wenn das zu vergleichende Element (wie z id
im Code der Frage) ist privat. In diesem Fall wirft VS2013 den folgenden Fehler für mich:
Fehler C2248: „Class1::id“: Zugriff auf privates Mitglied, das in Klasse „Class1“ deklariert ist, nicht möglich
Wie von erwähnt SkyWalker in den Kommentaren zu Pavels Antwort mit a friend
Deklaration hilft. Wenn Sie sich über die korrekte Syntax wundern, hier ist sie:
class Class1
{
public:
Class1(int id) : id(id) {}
private:
int id;
friend struct Class1Compare; // Use this for Pavel's first solution.
friend struct std::less<Class1>; // Use this for Pavel's second solution.
};
Code auf Ideone
Wenn Sie jedoch beispielsweise eine Zugangsfunktion für Ihr privates Mitglied haben getId()
zum id
wie folgt:
class Class1
{
public:
Class1(int id) : id(id) {}
int getId() const { return id; }
private:
int id;
};
dann können Sie es anstelle von a verwenden friend
Deklaration (d. h. Sie vergleichen lhs.getId() < rhs.getId()
). Seit C++11Sie können auch a verwenden Lambda-Ausdruck zum Pavels erste Lösung, anstatt eine Komparatorfunktionsobjektklasse zu definieren. Alles zusammengenommen könnte der Code wie folgt geschrieben werden:
auto comp = [](const Class1& lhs, const Class1& rhs){ return lhs.getId() < rhs.getId(); };
std::map<Class1, int, decltype(comp)> c2int(comp);
Code auf Ideone

Benutzer541686
auto operator<=>(Class1 const &) const = default;
zu deiner Klasse.
9936700cookie-checkWie kann ich std::maps mit benutzerdefinierten Typen als Schlüssel verwenden?yes
Mögliches Duplikat von C++ unordered_map mit einem benutzerdefinierten Klassentyp als Schlüssel
– Ciro Santilli Путлер Капут 六四事
18. April 2019 um 20:17 Uhr