Reputation: 465
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);
Upvotes: 4
Views: 410
Reputation: 30579
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_;
};
Or you could just write your own partial_sum
implementation for maps. That seems like it would be simpler to me.
Upvotes: 3