2012-12-18 12 views
5

Czy istnieje możliwość zmiany metody porównania std :: map po jej utworzeniu i zainicjowaniu? A może dopiero po utworzeniu?std :: map zmiana key_comp po inicjalizacji

Chcę jakoś zmienić zachowanie klasy zawierającej mapę, której nie można zmienić. Chcę zmienić jego zachowanie porównawcze, może przechodząc kolejną mapę.

+0

Czy widzisz tutaj funkcję, która pozwala ci to zrobić bezpośrednio: http://pl.cppreference.com/w/cpp/container/map? Jeśli nie, odpowiedź brzmi: nie ... – Nim

+2

Jest to parametr szablonu, więc musi zostać naprawiony w czasie kompilacji. Zmiana spowoduje zmianę typu kontenera. – v154c1

Odpowiedz

4

Może jest to możliwe, to niesprawdzone:

  1. Zdefiniuj swój własny komparator, który ma wewnętrznie wskaźnik do rzeczywistej realizacji funkcji porównania
  2. przekazać instancję tego do konstruktora mapa (musisz również wpisać mapę za pomocą tego komparatora).
  3. Ustaw prawdziwą implementację później (przed użyciem mapy), jeśli ustawisz ją później, nie wiesz wpływu na elementy wewnętrzne ...

testowałem, i to jest możliwe do wykonania powyższego, jednak zmienia funkcję porównawczą, czy istnieją elementy w drzewie mogą być katastrofalne ...

Zresztą - to wszystko brzmi zbyt podejrzany ....

+0

Jest OK. Mapa jest pusta. – djWann

+0

@djWann Myślę, że koszty wywołania porównań za pomocą wskaźnika funkcji za każdym razem znacznie spowolnią operacje 'map', jeśli się o to zatroszczysz. – rici

+0

@djWann Jeśli mapa jest pusta, dlaczego nie po prostu użyć nowej? Albo dwa całkowicie różne obiekty, albo tak długo jak komparator jest tą samą sygnaturą: 'my_map = std :: map <...> (& new_compare);' – rioki

1

Nie jest to możliwe. Można jednak utworzyć nową mapę z alternatywnymi kryteriami porównywania i dwoma konstruktorami iteratora, aby utworzyć mapę za pomocą elementów z pierwszego.

bool C1(const K&, const K&); 
bool C2(const K&, const K&); 

std::map<K, V, C1> orig; 
.... 
std::map<K, V, C2> alternative(orig.begin(), orig.end()); 
1

Nie, to nie jest możliwe, ponieważ jest skompilowany na mapie za pomocą szablonu argumentu.

Zobacz: http://www.cplusplus.com/reference/map/map/Porównaj jest tym, czego szukasz.

Co próbujesz zrobić?

Ponieważ masz klasę w ręce, której używasz jako Klucza, możesz zaimplementować operatora < lub funkcję porównania, aby zareagować na kontekst. Ponieważ możesz przekazać w pełni skonstruowany obiekt do funkcji porównania, powinno być możliwe przekazanie wszystkiego razem, aby zaimplementować zależne od kontekstu współczucie. Pytanie brzmi: dlaczego chcesz?

To jest zły pomysł zły pomysł, aby zmienić porównanie std :: map podczas działania, ponieważ spowoduje to niezdefiniowane zachowanie. Po prostu opiera się na tym, że zawartość std :: map jest "posortowana" (prawdopodobnie drzewo RB). Jeśli zmienisz funkcję zamawiania, nagle zmienisz kolejność logiczną; ale mapa nie zmieni się sama w magiczny sposób. Następne wywołanie do wstawienia lub znalezienia prawdopodobnie nie spełni twoich oczekiwań.

2

Nie, to niemożliwe. Komparator jest częścią typu mapy. Pytanie nie różni się od pytania, czy można zmienić numer int, aby przechowywać liczby zmiennoprzecinkowe.

Co ważniejsze, zamówienie dostarczone przez komparator jest integralną częścią wewnętrznej struktury mapy. Jeśli chcesz zmienić kolejność, struktura danych nie będzie już spójna.Jedyną realną opcją jest, aby odbudować nową mapę z elementami Stara mapa w odniesieniu do nowego porządku, ale to już możliwe:

std::map<T, V, Comp1> m1 = /* ... */; 
std::map<T, V, Comp2> m2(m1.begin(), m1.end()); 

Alternatywnie, można dokonać drugą mapę typu std::map<std::reference_wrapper<T const>, std::reference_wrapper<V>, Comp2> i wypełnić go z referencjami do oryginalnej mapy, ale zamówione zgodnie z Comp2. W takim przypadku odpowiedzialność za utrzymanie synchronizacji dwóch map spoczywa na użytkowniku. Zaawansowany kontener, taki jak Boost.Multiindex, może zrobić to dla Ciebie w bezpieczny sposób.

Powiązane problemy