Dear PH users,
Does anybody known how to, from a vector of pairs, sum the first value of each pair?
On the web, some people have posted the answer, as I show here:
[code]
#include #include #include #include int main()
{
std::vector > v;
v.push_back(std::make_pair(0,0));
v.push_back(std::make_pair(1,1));
v.push_back(std::make_pair(2,4));
v.push_back(std::make_pair(3,9));
const int sum_first = std::accumulate(v.begin(),v.end(),
static_cast(0),
boost::bind(&std::pair::first,_1));
}
[/code]
Problem is, with GCC this does not compile. I use Boost library version 1.40 and the STL supplied with Qt Creator 2.0.0.
Anybody an idea how to get this to compile?
When I compile, I get the following error message:
[code]
/usr/include/boost/bind/mem_fn.hpp:333: error: no matching function for call to
Comments
I have encountered precisely the same problem as you, but I don't believe it to be a problem with either GCC or the Boost libraries. In fact, I think I have a solution for you:
[code]#include
#include
#include
#include
#include // For std::cout, std::endl
#include // For std::plus
int main()
{
std::vector > v;
v.push_back(std::make_pair(0,0));
v.push_back(std::make_pair(1,1));
v.push_back(std::make_pair(2,4));
v.push_back(std::make_pair(3,9));
const int sum_first = std::accumulate(v.begin(),v.end(),
static_cast(0),
boost::bind(
std::plus(),
_1,
boost::bind(&std::pair::first, _2)
)
);
// Disable warning: "unused variable 'sum_first'"
std::cout << sum_first << std::endl;
}
[/code]
Now the explanation:
The first problem with the original code is that std::accumulate takes a binary_function as its final argument, which in turn takes:
[code]Arg1: accumulated value
Arg2: next value to be added[/code]
So, the boost::binder was binding the wrong argument (argument: '_1', where it should have been: '_2').
Next, this binder can only take a single argument (the std::pair to have its first element extracted), and so is a unary function. This is incompatible with std::accumulate.
So, to turn this unary function into a binary function (a function taking two arguments), as required by std::accumulate, it's necessary to use another outer bind with an instance of std::plus (or equivalent) to combine the next value with the accumulated total so far.
And that's it. Although it is somewhat complex (it takes more than a second to understand what's going on), the above code should do what you need. However, if you were to instead use boost::lambda, the code becomes a lot simpler:
[code]#include <numeric>
#include
#include
#include // For std::cout, std::endl
#include
#include
int main()
{
std::vector > v;
v.push_back(std::make_pair(0,0));
v.push_back(std::make_pair(1,1));
v.push_back(std::make_pair(2,4));
v.push_back(std::make_pair(3,9));
using boost::lambda::bind;
using boost::lambda::_1;
using boost::lambda::_2;
const int sum_first = std::accumulate(v.begin(),v.end(),
static_cast(0),
_1 + bind(&std::pair::first, _2));
// Disable warning: "unused variable 'sum_first'"
std::cout << sum_first << std::endl;
}[/code]
(Both examples tested and working on GCC 4.4.3, with Boost 1.43.0.)
Regards.