Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accumulate result from member function of elements in a container

I have a class, with a function which returns a count, like this:

class CTestClass
{
public:
    // ...
    size_t GetCount()const;
    // ...
};

And somewhere in my program I have a vector of objects of that class. I have a function to get the total count (sum of results of CTestClass::GetCount()), implemented like a normal loop:

size_t sum = 0;
for(vector<CTestClass>::const_iterator it = v.begin(); it != v.end(); ++it)
{
    sum += it->GetCount();
}

I want to refactor it to use the facilities available in the standard library, and I thought of accumulate. I've been able to do it by using a function object (easy), but I'm almost sure it can be done without declaring another object (I don't have C++11 or boost, so no lambdas, but I have TR1).
When looking for an answer, I've found these resources, but they don't solve the question:

  • This is pretty much the same question, and the answers provided are a loop, accumulate and functor, and accumulate and lambda, but there's an unanswered reference to bind and the like.
  • This answer to a similar question uses accumulate, plus and bind, but uses a data member instead of a member function.

So, is there a way to do this using bind, or something similar?

like image 795
MikMik Avatar asked Dec 07 '11 12:12

MikMik


2 Answers

I think the following should work:

using namespace std;
using namespace std::tr1;
using namespace std::tr1::placeholders;

accumulate(v.begin(), v.end(), 0,
           bind(plus<size_t>(), _1, bind(&C::GetCount, _2))
);
like image 170
fschoenm Avatar answered Sep 27 '22 00:09

fschoenm


This works, too:

class CTestClass
{
public:
    // ...
    size_t GetCount()const;
private:
    operator size_t() { return GetCount(); }
    // ...
    template <typename InputIterator, typename T>
    friend T std::accumulate(InputIterator, InputIterator, T);

};


std::vector<CTestClass> v;
// fill vector

size_t result = std::accumulate(v.begin(), v.end(), 0);

No TR1, no bind :)

like image 39
jrok Avatar answered Sep 24 '22 00:09

jrok