std::map, find i comparable

0

Witam.

Mam taki fragment kodu, a raczej chciałbym żeby to tak wyglądało (o ile to w ogóle możliwe).

class foo {
	public:
		foo(const char *x) {
			this->str = strdup(x);
		}
	
		char *str;
};

int main() {
	foo x("test");
	foo y("ala");

	map<foo*, int> m;
	m.insert(pair<foo*, int>(&x, 1));
	m.insert(pair<foo*, int>(&y, 2));

	foo a("test");
	map<foo*, int>::iterator it = m.find(&a);

	/* ... */
}

Wydaje mi się że trzeba by zdefiniować jakoś mechanizm porównywania który wykorzystuje find, no bo przecież skąd ma wiedzieć jak porównać obiekty foo. Wiem, że można podać klasę porównującą przy tworzeniu mapy

map<foo*, int, klasa>

ale mimo usilnych prób nie udało mi się zmusić tego do działania.
Czy taki mechanizm w ogóle jest możliwy do zaimplementowania?

0
struct comp
{
    bool operator()(const foo* p1,const foo* p2)const
    {
         return /* pomyśl */
    }
};
0

Kurde, byłem pewien, że własnie tak zrobiłem -_-
Przepraszam za zamieszanie, musiałem coś bardzo pomieszać.
Dzięki za pomoc [browar]

0

Witam.
Mam jeszcze problem z funkcją find().
Zdefiniowałem sobie operator(), i wygląda na to że wszystko "prawie" działa.
Mam sobie mapę takich wartości:

key value
"info" map<>
"creation date" string
"announce" string

W przypadku gdy do find podam mu "creation date" i "announce" znajduje poszukiwane pola, w przypadku "info" nie udaje mu się to. Wygląda na to że sam pomija etap porównywania z pierwszym kluczem, nie wiedzieć czemu.

std::map<BencodeVariable*, BencodeVariable*, BencodeVariable::BencodeVariableCompare>::iterator it;
BencodeVariable* var = new BencodeVariable(BencodeVariable::BENCODE_STR, "info");
	
it = i->bencodeValue.d->begin();
cout << (it++)->first->bencodeValue.s << endl;
cout << (it++)->first->bencodeValue.s << endl;
cout << it->first->bencodeValue.s << endl;

cout << "---------------------\n";
it = i->bencodeValue.d->find(var);
cout << "---------------------\n";
if (it != i->bencodeValue.d->end()) 
	cout << "Znalazlem"; 

Output: info
creation date
announce

Compare: creation date | info
Compare: announce | info


Widać że w mapie znajduje się pole info, ale w sekcji "Compare" (operator() wypluwa co z czym porównuje) jest pomijane.
0

Pokaż implementację operator().

0
 bool BencodeVariable::BencodeVariableCompare::
operator()(const BencodeVariable *x, const BencodeVariable *y) const {
	if (x->valueType == y->valueType) {
		switch(x->valueType)
		{
			case BENCODE_INT:
				return (x->bencodeValue.i == y->bencodeValue.i);
			case BENCODE_STR:{
				std::cout << "Compare: "<< x->bencodeValue.s << " " << y->bencodeValue.s <<  std::endl;
				
				return strcmp(x->bencodeValue.s, y->bencodeValue.s);}
			case BENCODE_LIST:
				return ((x->bencodeValue.l->size() == y->bencodeValue.l->size()) &&
				       (std::equal(x->bencodeValue.l->begin(), x->bencodeValue.l->end(), y->bencodeValue.l->begin())));
			case BENCODE_DICT:
				return ((x->bencodeValue.d->size() == y->bencodeValue.d->size()) &&
				       (std::equal(x->bencodeValue.d->begin(), x->bencodeValue.d->end(), y->bencodeValue.d->begin())));
		}
	}
	return false;
}
0

Warunki masz źle. operator() powinien zwrócić true, jeśli x < y, false - w każdym innym. Czyli nie:

return (x->bencodeValue.i == y->bencodeValue.i);

tylko

return x->bencodeValue.i < y->bencodeValue.i;
0

Yyy dzięki pomogło, nie rozumiem zupełnie czemu. Rozumiałbym jeśli zwracałoby błędne wyniki (w stylu "info" != "info") ale on nie brał pod uwagę w ogóle tego pola.
Czego mógłbym użyć zamiast std::equal, skoro ma być '<'

0

Zapewne dlatego nie brał pod uwagę, ponieważ zbiór nie był poprawnie posortowany przy tak skonstruowanym predykacie.

Jeśli chodzi o zamiennik equal, to raczej musisz go sobie sam napisać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1