如何使用std::partial_sum并输出到std::map?

How to use std::partial_sum and output to a std::map?

我想要一个只有 { {0,1},{1,2},{2,3},{3,4},{4,5} },c++11 的输出映射。有什么想法吗?

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 ); } 
);

这给出了编译错误:

/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);

你不能。至少不是直接的。问题是 std::map<int, int>::iterator::value_typestd::pair<const int, int>,并且 const 阻止了该类型的对象被分配给。

--

看看这个 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;
}

请注意,通过分配 op 的结果,每次迭代都会修改 sum。因为 sum.firstconst 那是不可能的;因此编译错误。

--

你可以做的是定义一个包含 std::map::iterator 并去掉 const 的迭代器类型。例如,以下将起作用:

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

或者您可以编写自己的 partial_sum 地图实现。这对我来说似乎更简单。