017: operator=()

代入演算子 operator=() を定義します。

コピー代入演算子、ムーブ代入演算子に加え、initializer_list 代入演算子の、計3種類を定義します。

template <typename T>
class myvector
{
...

    /**
     * @brief      Copy assignment operator. Replaces the contents with a copy of the
     *             contents of other.
     * @param[in]  other: Another container to use as data source.
     * @return     Own reference.
     * @throw      std::bad_alloc: If malloc() (or realloc()) fails to allocate storage.
     */
    self_type& operator=(const self_type& other)
    {
        if (this != &other) {
            // clear
            for (size_type i = 0; i < size_; i++) {
                heap_[i].~value_type();
            }
            size_ = 0;

            // re-allocate if needed
            if (other.size() > capacity_) {
                reallocation(other.size(), realloc_switcher());
            }

            // assign
            pointer p = heap_;
            for (auto i = other.cbegin(); i != other.cend(); ++i) {
                new(p++) value_type(*i);
            }
            size_ = other.size();
        }
        return *this;
    }

    /**
     * @brief      Move assignment operator. Replaces the contents with those of
     *             other using move semantics (i.e. the data in other is moved from
     *             other into this container). other is in a valid but unspecified
     *             state afterwards. In any case, all elements originally present
     *             in *this are either destroyed or replaced by element-wise move-assignment.
     * @param[in]  other: Another container to use as data source.
     * @return     Own reference.
     */
    self_type& operator=(self_type&& other) noexcept
    {
        if (this != &other) {
            // clear
            for (size_type i = 0; i < size_; i++) {
                heap_[i].~value_type();
            }
            size_ = 0;

            // swap
            std::swap(heap_, other.heap_);
            std::swap(size_, other.size_);
            std::swap(capacity_, other.capacity_);
        }
        return *this;
    }

    /**
     * @brief      Replaces the contents with those identified by initializer list ilist.
     * @param[in]  ilist: Initializer list to use as data source.
     * @return     Own reference.
     * @throw      std::length_error: If ilist size is greater than max_size().
     * @throw      std::bad_alloc: If malloc() (or realloc()) fails to allocate storage.
     */
    self_type& operator=(std::initializer_list<value_type> ilist)
    {
        size_type new_size = length_check(ilist.size());

        // clear
        for (size_type i = 0; i < size_; i++) {
            heap_[i].~value_type();
        }
        size_ = 0;

        // re-allocate if needed
        if (new_size > capacity_) {
            reallocation(new_size, realloc_switcher());
        }

        // assign
        pointer p = heap_;
        for (const auto& i: ilist) {
            new(p++) value_type(i);
        }
        size_ = ilist.size();

        return *this;
    }
    ...

};
コピー代入演算子は、自己代入チェックを行った後、①clear()相当の処理、②必要なら領域拡張、③コピーコンストラクタでコピー、という処理を行います。

ムーブ代入演算子は、自己代入チェックを行った後、swap()相当の処理を行います。

initializer_listの代入演算子は、引数の長さチェックを行った後、①clear()相当の処理、②必要なら領域拡張、③コピーコンストラクタでコピー、という処理を行います。

いずれの代入演算子も、戻り値は自身の非const参照になります。


全ソースコード: https://github.com/suomesta/myvector/tree/master/017

0 件のコメント:

コメントを投稿