I am simply trying to add values of a map defined in the program below:
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;
I get the following error:
Error C2893: Failed to specialize function template 'unknown-type std::plus::operator ()(_Ty1 &&,_Ty2 &&) const'
Maps are a part of the C++ STL. Maps are associative containers that store elements in a combination of key values and mapped values that follow a specific order. No two mapped values can have the same key values. In C++, maps store the key values in ascending order by default.
std::accumulate() is a built-in function in C++'s Standard Template Library. The function takes in a beginning iterator, an ending iterator, initial value, and (by default) computes the sum of the given initial value and the elements in the given range. The function can also be used for left folding.
Time complexity: k*log(n) where n is size of map, k is no. of elements inserted.
std::begin(floor_plan)
gives you an iterator pointing at std::map<int, int>::value_type
which is std::pair<const int, int>
. Since there is no operator+
defined for this pair type and an integer, your code fails to compile.
If you want to sum up all the mapped values from floor_plan
, you'd need to provide your own binary operator that is able to extract the second element of a dereferenced iterator passed in:
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; }
);
DEMO 1
Alternatively, you could exploit the Boost.Iterator library to extract the second element of a pair on the fly with 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);
DEMO 2
Another approach is to use the Boost.Range library along with its own implementation of the accumulate
algorithm:
#include <boost/range/numeric.hpp>
#include <boost/range/adaptor/map.hpp>
boost::accumulate(floor_plan | boost::adaptors::map_values, 0);
DEMO 3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With