Добавление всех значений карты с использованием std :: аккумулята

Я просто пытаюсь добавить значения карты, определенной в программе ниже:

std::map<int, int> floor_plan;

const size_t distance = std::accumulate(std::begin(floor_plan), std::end(floor_plan), 0);

std::cout << "Total: " << distance;

Я получаю следующую ошибку:

Ошибка C2893: не удалось специализировать шаблон функции ‘неизвестный тип std :: plus :: operator () (_ Ty1 &&, _Ty2 &&) const ‘

11

Решение

std::begin(floor_plan) дает вам итератор, указывающий на std::map<int, int>::value_type который std::pair<const int, int>, Так как нет operator+ определенный для этого типа пары и целого числа, ваш код не может быть скомпилирован.

Опция 1

Если вы хотите суммировать все сопоставленные значения из floor_planвам нужно будет предоставить свой собственный бинарный оператор, который сможет извлечь второй элемент разыменованного итератора, переданного в:

std::accumulate(std::begin(floor_plan)
, std::end(floor_plan)
, 0
, [] (int value, const std::map<int, int>::value_type& p)
{ return value + p.second; }
);

ДЕМО 1

Вариант № 2

Кроме того, вы можете использовать Boost.Iterator библиотека для извлечения второго элемента пары на лету с boost::make_transform_iterator:

#include <boost/iterator/transform_iterator.hpp>
#include <functional>

auto second = std::mem_fn(&std::map<int, int>::value_type::second);
std::accumulate(boost::make_transform_iterator(std::begin(floor_plan), second)
, boost::make_transform_iterator(std::end(floor_plan), second)
, 0);

ДЕМО 2

Вариант № 3

Другой подход заключается в использовании Boost.Range библиотека вместе с собственной реализацией accumulate алгоритм:

#include <boost/range/numeric.hpp>
#include <boost/range/adaptor/map.hpp>

boost::accumulate(floor_plan | boost::adaptors::map_values, 0);

ДЕМО 3

15

Другие решения

Петр С. Ответ правильный, но если это не разовое задание, лучше сделать простой удобный функтор для таких заданий:

struct AddValues
{
template<class Value, class Pair>
Value operator()(Value value, const Pair& pair) const
{
return value + pair.second;
}
};

const size_t distance = std::accumulate(plan.begin(), plan.end(), 0, AddValues());

Спасибо operator() Вы можете использовать этот функтор для любого map в вашем коде. Это очень похоже на прозрачный компаратор, но это прозрачный «сумматор».

3

Я покажу вам не только, как это работает.

accumulate Возможная реализация как ниже(как мы можем суммировать от базового значения, так что есть init значение):

template<class InputIt, class T, class BinaryOperation>
T accumulate(InputIt first, InputIt last, T init,
BinaryOperation op)
{
for (; first != last; ++first) {
init = op(std::move(init), *first); // std::move since C++20
}
return init;
}

Поэтому, когда мы хотим получить sum/product из vectorэто может понравиться так:

vector<int> vec(5);
std::iota(vec.begin(), vec.end(), 1);

cout<<"vec: ";// output vec
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(cout, ", "));
// vec: 1, 2, 3, 4, 5,

cout<<"\n vec sum is: "<<accumulate(vec.begin(), vec.end(), 0)<<endl;
// vec sum is: 15

cout<<"vec product is: "<<accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>())<<endl;
// vec product is: 120

Относительно std::mapВы хотите суммировать второе значение mapтак что вы должны получить каждый second item в карте. Так что вы должны получить value_type в map а затем получить второй предмет. value_type в map определяется как ниже:

template <typename Key, typename Value, class Compare = std::less<Key>>
class map{
// using re_tree to sort
typedef Key    key_type;

// rb_tree value type
typedef std::pair<key_type, value_type> value_type;
};

Например, получить сумму всех second/first значение:

typedef map<string, int> IdPrice;
IdPrice idPrice = {{"001", 100}, {"002", 300}, {"003", 500}};

int sum = accumulate(idPrice.begin(), idPrice.end(), 0, [](int v, const IdPrice::value_type& pair){
return v + pair.second;
// if we want to sum the first item, change it to
// return v + pair.first;
});
cout<<"price sum is: "<<sum<<endl; // price sum is: 900

Пара v в выше lambda funtion, хранит сумму tmp со значением init 0.

0
По вопросам рекламы [email protected]