4

I want an output map that has { {0,1},{1,2},{2,3},{3,4},{4,5} }, c++11 only. Any ideas?

std::map<int, int> m, out; for( auto i=0; i < 5; ++i ) m[i] = 1; std::partial_sum( m.begin(), m.end(), std::inserter( out, out.begin() ), []( const std::pair<int,int>& a, const std::pair<int,int>& b ) { return std::pair<int,int>( a.first, a.second + b.second ); } ); 

This gives compile error:

/usr/include/c++/5/bits/stl_pair.h: In instantiation of ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_U1, _U2>&&) [with _U1 = int; _U2 = int; _T1 = const int; _T2 = int]’: /usr/include/c++/5/bits/stl_numeric.h:295:12: required from ‘_OutputIterator std::partial_sum(_InputIterator, _InputIterator, _OutputIterator, _BinaryOperation) [with _InputIterator = std::_Rb_tree_iterator<std::pair<const int, int> >; _OutputIterator = std::insert_iterator<std::map<int, int> >; _BinaryOperation = main()::<lambda(const std::pair<int, int>&, const std::pair<int, int>&)>]’ ../src/test_cumsum.cpp:43:130: required from here /usr/include/c++/5/bits/stl_pair.h:188:10: error: assignment of read-only member ‘std::pair<const int, int>::first’ first = std::forward<_U1>(__p.first); 

1 Answer 1

3

You can't. Not directly, at least. The issue is that std::map<int, int>::iterator::value_type is std::pair<const int, int>, and that const prevents an object of that type from being assigned to.

--

Take a look at this possible implementation for std::partial_sum:

template<class InputIt, class OutputIt, class BinaryOperation> constexpr // since C++20 OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first, BinaryOperation op) { if (first == last) return d_first; typename std::iterator_traits<InputIt>::value_type sum = *first; *d_first = sum; while (++first != last) { sum = op(std::move(sum), *first); // std::move since C++20 *++d_first = sum; } return ++d_first; } 

Note that sum gets modified each iteration by assigning the result of op. Because sum.first is const that's not possible; hence the compilation error.

--

What you could do is define an iterator type that wraps std::map::iterator and strips out the const. For example, the following will work:

template <typename Pair> struct RemoveFirstConstHelper { using type = Pair; }; template <typename T1, typename T2> struct RemoveFirstConstHelper<std::pair<const T1, T2>> { using type = std::pair<T1, T2>; }; template <typename MapIterator> class RemoveFirstConstIter { public: using difference_type = std::ptrdiff_t; using value_type = typename RemoveFirstConstHelper<typename MapIterator::value_type>::type; using pointer = value_type*; using reference = value_type; using iterator_category = std::input_iterator_tag; RemoveFirstConstIter(MapIterator it) : it_{it} {} reference operator*() { return *it_; } RemoveFirstConstIter& operator++() { ++it_; return *this; } RemoveFirstConstIter operator++(int) const { RemoveFirstConstIter temp{*this}; ++temp; return temp; } bool operator==(const RemoveFirstConstIter& other) const { return it_ == other.it_; } bool operator!=(const RemoveFirstConstIter& other) const { return !(*this == other); } private: MapIterator it_; }; 

Live Demo

Or you could just write your own partial_sum implementation for maps. That seems like it would be simpler to me.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks for the answer. I see now, that keys cannot be modified in map, thus the error. More complicated than I thought it would be.
Well formatted answer with good citations. Well done.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.