I have std::map<int, std::pair<short, float> >
, and I need to find the minimal short
in this map. How can I use boost::bind
with std::min_element()
for this?
boost::lambda
?
boost::bind is a generalization of the standard functions std::bind1st and std::bind2nd. It supports arbitrary function objects, functions, function pointers, and member function pointers, and is able to bind any argument to a specific value or route input arguments into arbitrary positions.
_1 is a placeholder. Boost. Bind defines placeholders from _1 to _9 . These placeholders tell boost::bind() to return a function object that expects as many parameters as the placeholder with the greatest number.
boost::function makes it possible to define a pointer to a function with a specific signature. Example 40.1 defines a pointer f that can point to functions that expect a parameter of type const char* and return a value of type int .
The map
iterator will give you a pair
where first
is the int
key and second
is the map's pair
value, so if you had an iterator it
, you'd want the minimum of all the it->second.first
values. The min_element
function expects a comparison function for its third argument, so you need to build a comparison function that projects second.first
of its two arguments.
We'll start with some typedefs to make the code more readable:
typedef std::pair<short, float> val_type;
typedef std::map<int, val_type> map_type;
map_type m;
We're going to use Boost.Lambda for its overloaded operators, allowing us to use operator<
. Boost.Bind can bind member variables as well as member functions, so we'll take advantage of that, too.
#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;
That will also work with boost::lambda::bind
.
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;
(Of course, somebody's going to complain that this is an abuse of STL and that these are extensions not in the C++ standard…)
bind
cannot do this by itself, because first
and second
are exposed as fields, not methods (so you can't get away with something like mem_fun
).
You could do this using your own functor of course though:
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;
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With