Mam std::map<int, std::pair<short, float> >
, i muszę znaleźć minimalną short
na tej mapie. Jak mogę użyć do tego celu boost::bind
z std::min_element()
?Jak mogę użyć Boost.Bind dla typów złożonych?
boost::lambda
?
Mam std::map<int, std::pair<short, float> >
, i muszę znaleźć minimalną short
na tej mapie. Jak mogę użyć do tego celu boost::bind
z std::min_element()
?Jak mogę użyć Boost.Bind dla typów złożonych?
boost::lambda
?
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
.
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;
}
};
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 ...)
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. –
Znany również jako 'select1st' w niektórych bibliotekach C++. – ephemient
@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. –