2011-01-25 1 views

ответ

6

map итератор даст вам pair где first является int ключом и second является pair значения для этой карты, так что если вы ч ad iterator it, вы хотите, чтобы минимум всех значений it->second.first. Функция min_element ожидает функцию сравнения для своего третьего аргумента, поэтому вам нужно построить функцию сравнения, которая реализует second.first из двух своих аргументов.

Мы начнем с некоторыми определениями типов, чтобы сделать код более читаемым:

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

Мы будем использовать Boost.Lambda для своих перегруженных операторов, что позволяет нам использовать operator<. Boost.Bind может связывать переменные-члены, а также функции-члены, поэтому мы также воспользуемся этим.

#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; 

Это также будет работать с boost::lambda::bind.

2

bind не может сделать это сам по себе, потому что first и second подвергаются как поля, а не методы (так что вы не можете уйти с чем-то вроде mem_fun).

Вы можете сделать это, используя свой собственный функтор, конечно, хотя:

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

Также известен как 'select1st' в некоторых библиотеках C++. – ephemient

+0

@ephemient: True - не знал, что он уже включен в STL SGI. В этом случае я бы рекомендовал оставить это имя таким образом, потому что SGI поддерживает любой пара-подобный интерфейс, в то время как этот работает только с 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; 

(Конечно, кто-то собирается жаловаться, что это злоупотребление STL и что эти расширения не в C++ стандарт ...)

+0

Ну, я бы жаловался на нестандартные расширения, но, насколько «STL-злоупотребление», я думаю, что это прекрасно :) +1. К счастью, нестандартные биты легко писать сами. –