Tengo std::map<int, std::pair<short, float> >
, y necesito encontrar el mínimo short
en este mapa. ¿Cómo puedo usar boost::bind
con std::min_element()
para esto?¿Cómo puedo usar Boost.Bind en tipos compuestos?
boost::lambda
?
Tengo std::map<int, std::pair<short, float> >
, y necesito encontrar el mínimo short
en este mapa. ¿Cómo puedo usar boost::bind
con std::min_element()
para esto?¿Cómo puedo usar Boost.Bind en tipos compuestos?
boost::lambda
?
el iterador map
te dará un pair
donde first
es la clave int
y second
es el valor del mapa pair
, así que si h y un iterador it
, querrá el mínimo de todos los valores it->second.first
. La función min_element
espera una función de comparación para su tercer argumento, por lo que debe crear una función de comparación que proyecte second.first
de sus dos argumentos.
Vamos a empezar con algunos typedefs para hacer el código más legible:
typedef std::pair<short, float> val_type;
typedef std::map<int, val_type> map_type;
map_type m;
vamos a utilizar Boost.Lambda por sus operadores sobrecargados, que nos permite utilizar operator<
. Boost.Bind puede vincular variables miembro así como funciones de miembros, por lo que también lo aprovecharemos.
#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;
Eso también funcionará con boost::lambda::bind
.
bind
no puede hacer esto por sí mismo, porque first
y second
están expuestos como campos, no métodos (por lo que no puede salir con algo así como mem_fun
).
Usted puede hacer esto utilizando su propio funtor, por supuesto, sin embargo:
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;
(Por supuesto, alguien va a quejarse de que esto es un abuso de STL y que éstas son extensiones no están en el C++ estándar ...)
Bueno, me quejaría de las extensiones no estándar, pero en lo que respecta al "abuso de STL" creo que está perfectamente bien :) +1. Afortunadamente, los bits no estándar son fáciles de escribir. –
También conocido como 'select1st' en algunas bibliotecas C++. – ephemient
@ephemient: cierto: no era consciente de que ya estaba incluido con el STL de SGI. En ese caso, recomendaría dejar el nombre de esta manera porque SGI admite cualquier interfaz parecida a una pareja, mientras que esta solo funciona con std :: pair. –