2011-01-25 20 views

Odpowiedz

6

map iterator daje pair gdzie first jest kluczem int i second jest mapa w pair wartość, więc jeśli h ad iterator it, potrzebujesz minimum wszystkich wartości it->second.first. Funkcja min_element oczekuje funkcji porównania dla trzeciego argumentu, więc musisz zbudować funkcję porównawczą, która wyświetla second.first z dwóch argumentów.

zaczniemy z niektórych typedefs aby kod był bardziej czytelny:

typedef std::pair<short, float> val_type; 
typedef std::map<int, val_type> map_type; 
map_type m; 

Będziemy używać Boost.Lambda dla swoich przeciążonych operatorów, co pozwala nam korzystać operator<. Boost.Bind może wiązać zmienne składowe, a także funkcje składowe, więc my też to wykorzystamy.

#include <boost/bind.hpp> 
#include <boost/lambda/lambda.hpp> 
using boost::bind; 

// Comparison is (_1.second.first < _2.second.first) 
std::cout << 
    std::min_element(m.begin(), m.end(), 
    bind(&val_type::first, bind(&map_type::iterator::value_type::second, _1)) 
    < 
    bind(&val_type::first, bind(&map_type::iterator::value_type::second, _2)) 
)->second.first; 

Będzie to również działać z boost::lambda::bind.

2

bind nie może tego zrobić sam, bo first i second narażone są jako pola, a nie metodami (więc nie można uciec z czymś mem_fun).

Można to zrobić za pomocą własnego funktor oczywiście mimo:

template <typename F, typename S> 
struct select_first : std::binary_function<std::pair<F, S>&, F&> 
{ 
    F& operator()(std::pair<F, S>& toConvert) 
    { 
     return toConvert.first; 
    } 
}; 
+1

Znany również jako 'select1st' w niektórych bibliotekach C++. – ephemient

+0

@ephemient: True - nie był świadomy, że był już dołączony do STL SGI. W takim przypadku polecam pozostawienie nazwy w ten sposób, ponieważ SGI obsługuje dowolny interfejs podobny do parowania, podczas gdy ten działa tylko z std :: pair. –

5
min_element(map.begin(), map.end(), 
      compose2(less<short>(), 
        compose1(select1st<pair<short, float> >(), 
           select2nd<map<int, pair<short, float> 
              >::value_type>()), 
        compose1(select1st<pair<short, float> >(), 
           select2nd<map<int, pair<short, float> 
              >::value_type>())) 
      ).second.first; 

(Oczywiście, ktoś będzie narzekać, że jest to nadużycie STL i że są to rozszerzenia nie w C++ norma ...)

+0

Cóż, chciałbym narzekać na niestandardowe rozszerzenia, ale jeśli chodzi o "nadużycie STL", to myślę, że wszystko jest w porządku :) +1. Na szczęście niestandardowe bity można łatwo napisać samemu. –

Powiązane problemy