如何使用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_type
是 std::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.first
是 const
那是不可能的;因此编译错误。
--
你可以做的是定义一个包含 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_;
};
或者您可以编写自己的 partial_sum
地图实现。这对我来说似乎更简单。
我想要一个只有 { {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_type
是 std::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.first
是 const
那是不可能的;因此编译错误。
--
你可以做的是定义一个包含 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_;
};
或者您可以编写自己的 partial_sum
地图实现。这对我来说似乎更简单。