Что лучший способ состоит в том, чтобы суммировать результат функции членства для всех элементов в контейнере?

Скажем, у меня есть следующий объект:

struct Foo
{
    int size() { return 2; }
};

Каков лучший способ (самый удобный в сопровождении, читаемый, и т.д.) для получения общего количества size из всех объектов в a vector<Foo>? Я отправлю свое решение, но я интересуюсь лучшими идеями.

Обновление:

До сих пор мы имеем:

  • станд.:: накопитесь и функтор
  • станд.:: накопитесь и лямбда-выражение
  • простой для цикла

Есть ли какие-либо другие осуществимые решения? Можно ли сделать что-то удобным в сопровождении использованием boost::bind или std::bind1st/2nd?

11
задан Michael Kristofik 8 July 2010 в 16:47
поделиться

4 ответа

В дополнение к собственному предложению, если ваш компилятор поддерживает лямбда-выражения 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();});
25
ответ дан 3 December 2019 в 01:00
поделиться

Вот практическое решение:

typedef std::vector<Foo> FooVector;
FooVector vf;
int totalSize = 0;
for (FooVector::const_iterator it = vf.begin(); it != vf.end(); ++it) {
  totalSize += it->size();
}
4
ответ дан 3 December 2019 в 01:00
поделиться

Я считаю, что итераторы 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 .

7
ответ дан 3 December 2019 в 01:00
поделиться

Используйте 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());
7
ответ дан 3 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: