Как я могу использовать Boost.Bind для составных типов? - PullRequest
8 голосов
/ 25 января 2011

У меня есть std::map<int, std::pair<short, float> >, и мне нужно найти минимальный short на этой карте.Как я могу использовать boost::bind с std::min_element() для этого?

boost::lambda?

Ответы [ 3 ]

6 голосов
/ 25 января 2011

Итератор map даст вам pair, где first - это ключ int, а second - это значение pair карты, поэтому, если у вас был итератор 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.

5 голосов
/ 25 января 2011
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 ++…)

2 голосов
/ 25 января 2011

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;
    }
};
...