#c #c 11 #stdmap
#c #c 11 #stdmap
Вопрос:
Мне нужна карта вывода, которая имеет { {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>amp; a, const std::pair<int,int>amp; 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>amp; std::pair<_T1, _T2>::operator=(std::pair<_U1, _U2>amp;amp;) [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>amp;, const std::pair<int, int>amp;)>]’
../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:
Вы не можете. По крайней мере, не напрямую. Проблема в том, что std::map<int, int>::iterator::value_type
есть std::pair<const int, int>
, и это const
предотвращает присвоение объекту этого типа.
—
Взгляните на эту возможную реализацию для 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;
}
Обратите внимание, что это sum
изменяется на каждой итерации путем присвоения результата op
. Потому 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_;
}
RemoveFirstConstIteramp; operator ()
{
it_;
return *this;
}
RemoveFirstConstIter operator (int) const
{
RemoveFirstConstIter temp{*this};
temp;
return temp;
}
bool operator==(const RemoveFirstConstIteramp; other) const
{
return it_ == other.it_;
}
bool operator!=(const RemoveFirstConstIteramp; other) const
{
return !(*this == other);
}
private:
MapIterator it_;
};
Или вы могли бы просто написать свою собственную partial_sum
реализацию для maps. Мне кажется, что это было бы проще.
Комментарии:
1. спасибо за ответ. Теперь я вижу, что ключи не могут быть изменены в map, отсюда и ошибка. Сложнее, чем я думал.
2. Хорошо отформатированный ответ с хорошими цитатами. Молодец.