hash_map と次のようなコードがあるとします。
// i is an iterator
i = hash_map.erase(i)
しかし、GCC の STL は消去時にイテレータを返さず、void を返します。今のようなコードです
hash_map.erase(i++)
安全 (つまり、イテレータを無効にしない、またはその他の予期しないまたは不快なことをしない)? これは hash_map であることに注意してください。
i
はい、現在の値が消去される前に の値が次の値に設定されるため、これは安全です。
ハッシュ化されたコンテナに関する SGI のドキュメントによると、無効化は消去されていない要素に対しては発生せず、サイズ変更に対しても発生しません (挿入によってサイズ変更が発生するかどうかについては言及されていないため、可能性として認めます)---しかし、後者の場合、反復順序が変更されます。しかし、これはここでは当てはまりません。トラバーサル中などにわざわざコンテナのサイズを変更しない限りです。:-)
消去をカプセル化して、使用するすべてのコンテナーに同じインターフェイスを提供できます。
namespace detail {
template<typename Container, typename R>
struct SelectErase {
// by default, assume the next iterator is returned
template<typename Iterator>
Iterator erase(Container& c, Iterator where) {
return c.erase(where);
}
};
// specialize on return type void
template<typename Container>
struct SelectErase<Container, void> {
template<typename Iterator>
Iterator erase(Container& c, Iterator where) {
Iterator next (where);
++next;
c.erase(where);
return next;
}
};
template<typename I, typename Container, typename R>
SelectErase<Container,R> select_erase(R (Container::*)(I)) {
return SelectErase<Container,R>();
}
} // namespace detail
template<typename Container, typename Iterator>
Iterator erase(Container& container, Iterator where) {
return detail::select_erase<Iterator>(&Container::erase).erase(container, where);
}
これには、次のいずれかが必要です。
パレードに雨を降らせるのは嫌いですが、あなたの提案は安全ではないと思います。
i++ は後置インクリメント演算子です。つまり、消去の呼び出し後に i がインクリメントされます。しかし、erase は、消去される要素を指すすべての反復子を無効にします。したがって、i がインクリメントされるまでには、それはもはや有効ではありません。
運が良ければ、ある日突然機能しなくなるまで、正しく機能する可能性があります。
私が知る限り、これを回避する方法はありませんが、次のようなものです。
// tmp and i are both iterators
tmp = i;
++i;
hash_map.erase(tmp);