028: erase()

erase() を定義します。

引数が単発の 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 件のコメント:

コメントを投稿