メモの日々


2019年05月08日(水) [長年日記]

[c++] reverse_iteratorが指す要素の削除

reverse_iteratorが指す要素の削除方法をメモしておく。Effective STLの第28項「reverse_iteratorの基底iteratorの使い方を理解しよう」に説明がある。

  • コンテナのerase()メソッドはreverse_iteratorを受け付けないので、reverse_iteratorのbase()メソッドによりiteratorオブジェクトを取得する必要がある。
  • base()が返すイテレータが指す要素はreverse_iteratorが指す要素からend()方向に1つずれているので、erase()に渡す際にはイテレータの位置を調整する必要がある。調整には (++rit).base() のようにreverse_iteratorを1つ進めてからbase()を呼ぶべしとEffective STLにある。
 rend()                         rit                         rbegin()
       +-------+-------+-----+-------+-------+-----+-------+-------+
       |   a   |   b   | ... |   h   |   i   | ... |   y   |   z   |
       +-------+-------+-----+-------+-------+-----+-------+-------+
         begin()                     rit.base()                      end()
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

int main()
{
  std::vector<int> v(10);
  std::iota(v.begin(), v.end(), 1);

  auto rit = std::find_if(
      v.rbegin(),
      v.rend(),
      [](int i) { return i % 3 == 0; });
  if (rit != v.rend()) {
    // reverse_iterator::base()が返すイテレータは指す要素が異なるので調整が必要
    // see Effective STL 第28項
    v.erase((++rit).base());
  }

  for (const auto& e : v) {
    std::cout << e << " ";
  }
  std::cout << std::endl;
}
1 2 3 4 5 6 7 8 10