Скажем, у меня есть следующий объект:
struct Foo
{
int size() { return 2; }
};
Каков лучший способ (самый удобный в сопровождении, читаемый, и т.д.) для получения общего количества size
из всех объектов в a vector<Foo>
? Я отправлю свое решение, но я интересуюсь лучшими идеями.
Обновление:
До сих пор мы имеем:
Есть ли какие-либо другие осуществимые решения? Можно ли сделать что-то удобным в сопровождении использованием boost::bind
или std::bind1st/2nd
?
В дополнение к собственному предложению, если ваш компилятор поддерживает лямбда-выражения C++0x, вы можете использовать эту более короткую версию:
std::vector<Foo> vf;
// do something to populate vf
int totalSize = std::accumulate(vf.begin(),
vf.end(),
0,
[](int sum, const Foo& elem){ return sum + elem.size();});
Вот практическое решение:
typedef std::vector<Foo> FooVector;
FooVector vf;
int totalSize = 0;
for (FooVector::const_iterator it = vf.begin(); it != vf.end(); ++it) {
totalSize += it->size();
}
Я считаю, что итераторы Boost отличаются элегантностью, хотя они могут быть немного подробными (алгоритмы на основе диапазона могут сделать это лучше) . В этом случае итераторы преобразования могут выполнять эту работу:
#include <boost/iterator/transform_iterator.hpp>
//...
int totalSize = std::accumulate(
boost::make_transform_iterator(vf.begin(), std::mem_fn(&Foo::size)),
boost::make_transform_iterator(vf.end(), std::mem_fn(&Foo::size)),0);
Edit: заменено " boost :: bind (& Foo :: size, _1)
" на " std :: mem_fn (& Foo :: size)
"
Edit: я только что обнаружил, что библиотека Boost.Range была обновлена, чтобы ввести алгоритмы диапазона! Вот новая версия того же решения:
#include <boost/range/distance.hpp> // numeric.hpp needs it (a bug?)
#include <boost/range/numeric.hpp> // accumulate
#include <boost/range/adaptor/transformed.hpp> // transformed
//...
int totalSize = boost::accumulate(
vf | boost::adaptors::transformed(std::mem_fn(Foo::size)), 0);
Примечание: характеристики примерно такие же (см. Мой комментарий): внутри преобразованный
использует transorm_iterator
.
Используйте std :: accumulate и функтор.
#include <functional>
#include <numeric>
struct SumSizes : public std::binary_function<int, Foo, int>
{
int operator()(int total, const Foo& elem) const
{
return total + elem.size();
}
};
std::vector<Foo> vf;
// do something to populate vf
int totalSize = std::accumulate(vf.begin(),
vf.end(),
0,
SumSizes());