引数が単発の iterator と、範囲の iterator の2種類実装します。
template <typename T>
class myvector
{
...
/**
* @brief Erases the specified elements from the container. Removes the
* element at pos.
* Invalidates iterators and references at or after the point of
* the erase, including the end() iterator. The iterator pos must
* be valid and dereferenceable. Thus the end() iterator (which is
* valid, but is not dereferencable) cannot be used as a value for
* pos.
* @param[in] pos: Iterator to the element to remove.
* @return Iterator following the last removed element. If the iterator pos
* refers to the last element, the end() iterator is returned.
*/
iterator erase(const_iterator pos)
{
// calculate distance
size_type distance = mydistance(static_cast<const_iterator>(&heap_[0]), pos, std::random_access_iterator_tag());
// remove one element
heap_[distance].~value_type();
// slide elements after pos
decremental_slide(distance, 1, slide_switcher());
size_--;
return static_cast<iterator>(&heap_[distance]);
}
/**
* @brief Erases the specified elements from the container. Removes the
* elements in the range [first, last).
* Invalidates iterators and references at or after the point of
* the erase, including the end() iterator. The iterator first
* does not need to be dereferenceable if first==last: erasing an
* empty range is a no-op.
* @param[in] first: The first of range of elements to remove.
* @param[in] last: The last of range of elements to remove.
*/
iterator erase(const_iterator first, const_iterator last)
{
// calculate distance
size_type distance = mydistance(static_cast<const_iterator>(&heap_[0]), first, std::random_access_iterator_tag());
if (first == last) {
return mynext(&(heap_[0]), distance, std::random_access_iterator_tag());
}
// calculate count
size_type count = mydistance(first, last, std::random_access_iterator_tag());
// remove elements
for (size_type i = distance; i < (distance + count); i++) {
heap_[i].~value_type();
}
// slide elements after first
decremental_slide(distance, count, slide_switcher());
size_ -= count;
return static_cast<iterator>(&heap_[distance]);
}
...
private:
/**
* @brief Does slide elements into decremental direction.
* value_type shall be TriviallyCopyable.
* @param[in] pos: Element index which is start position of moving.
* @param[in] count: The size of the elements to be moved.
* @param[in] trivially_copyable_tag: Function switcher according to value_type characteristic.
*/
void decremental_slide(size_type pos, size_type count, trivially_copyable_tag)
{
for (size_type i = pos; (i + count) < size_; i++) {
heap_[i] = heap_[i + count];
}
}
/**
* @brief Does slide elements into decremental direction.
* value_type shall be MoveConstructible.
* @param[in] pos: Element index which is start position of moving.
* @param[in] count: The size of the elements to be moved.
* @param[in] move_constructible_tag: Function switcher according to value_type characteristic.
*/
void decremental_slide(size_type pos, size_type count, move_constructible_tag)
{
for (size_type i = pos; (i + count) < size_; i++) {
new(&heap_[i]) value_type(std::move(heap_[i + count]));
}
}
/**
* @brief Does slide elements into decremental direction.
* value_type shall be CopyConstructible.
* @param[in] pos: Element index which is start position of moving.
* @param[in] count: The size of the elements to be moved.
* @param[in] copy_constructible_tag: Function switcher according to value_type characteristic.
*/
void decremental_slide(size_type pos, size_type count, copy_constructible_tag)
{
for (size_type i = pos; (i + count) < size_; i++) {
new(&heap_[i]) value_type(heap_[i + count]);
}
}
};
補助関数 decremental_slide() を定義します。これは insert() を実装するときに作成して incremental_slide() と似た関数で、要素を前方へズラします。
eraseの中身は、①要素削除後のサイズの計算、②要素の削除(デストラクタ)、③要素の移動、となります。この処理の流れも、insert() に似たものになります。
全ソースコード:
https://github.com/suomesta/myvector/tree/master/028
0 件のコメント:
コメントを投稿