簡體   English   中英

C++ 中的迭代器和常量迭代器?

[英]Iterators and Const iterators in C++?

假設我有兩個類,第一個:

class IntMatrix::iterator {
private:
    const IntMatrix *int_matrix;
    int index;

    iterator(const IntMatrix *int_matrix, int index);

    friend class IntMatrix;

public:
    int &operator*() const;

    iterator &operator++();

    iterator operator++(int);

    bool operator==(const iterator &it) const;

    bool operator!=(const iterator &it) const;

    iterator(const iterator &) = default;

    iterator &operator=(const iterator &) = default;

    ~iterator() = default;
};

第二個是:

class IntMatrix::const_iterator {
private:
    const IntMatrix *int_matrix;
    int index;

    const_iterator(const IntMatrix *int_matrix, int index);

    friend class IntMatrix;

public:
    const int &operator*() const;

    const_iterator &operator++();

    const_iterator operator++(int);

    bool operator==(const const_iterator &it) const;

    bool operator!=(const const_iterator &it) const;

    const_iterator(const const_iterator &) = default;

    const_iterator &operator=(const const_iterator &) = default;

    ~const_iterator() = default;
};

我如何防止代碼重復,因為實現是 99% 相同的? generics在這里或inheritance怎么樣?

它們是如何實現的示例:

int &IntMatrix::iterator::operator*() const {
    return int_matrix->data[index];
}

const int &IntMatrix::const_iterator::operator*() const {
    return int_matrix->data[index];
}

另外,我希望 In main 允許以下內容:

IntMatrix::iterator it;

更新:我正在嘗試通過以下方式在名為 Matrix 的通用 class 上實現給定的解決方案:(注意顯示的代碼在我的課堂上都是公開的)

template<typename T>
class iterator_impl;

template<typename T>
iterator_impl<T> begin(){
    return iterator(this, 0);
}

template<typename T>
iterator_impl<T> end(){
    return iterator(this, size());
}

template<typename T>
iterator_impl<const T> begin() const
{
    return const_iterator(this, 0);
}

template<typename T>
iterator_impl<const T> end() const
{
    return const_iterator(this, size());
}

template<typename T>
class iterator_impl{
private:
    const Matrix<T> *matrix;
    int index;
    friend class Matrix<T>;

public:
    iterator_impl(const iterator_impl &) = default;

    iterator_impl &operator=(const iterator_impl &) = default;

    ~iterator_impl() = default;

    iterator_impl(const Matrix<T> *int_matrix, int index)
            : matrix(int_matrix), index(index) {}

    iterator_impl &operator++()
    {
        ++index;
        return *this;
    }

    iterator_impl operator++(int)
    {
        iterator_impl result = *this;
        ++*this;
        return result;
    }

    bool operator==(const iterator_impl &it) const
    {
        return index == it.index;
    }

    bool operator!=(const iterator_impl &it) const
    {
        return !(*this == it);
    }

    T &operator*() const {
        if (index < 0 || index > matrix->size() - 1) {
            throw Matrix<T>::AccessIllegalElement();
        }
        return matrix->data[index];
    }
};
template<typename T>
using iterator = iterator_impl<T>;

template<typename T>
using const_iterator = iterator_impl<const T>;

我遇到了一些錯誤,例如:

在非靜態成員 function 之外無效使用“this”返回迭代器(this,0);

一種方法是將實現變為 class 模板,然后為const和非const實例化創建別名。

另外,我希望 In main 允許類似: IntMatrix::iterator it;

然后,您需要添加一個默認構造函數。

例子:

#include <cstddef>
#include <type_traits>

// in the .hpp file:
class IntMatrix {
private:
    int data[10];     // just an example
    size_t size = 10; // just an example

    template<typename T>
    class iterator_impl;

public:
    // two typedefs using the template:
    using iterator = iterator_impl<int>;
    using const_iterator = iterator_impl<const int>;

    const_iterator cbegin() const;
    const_iterator cend() const;
    const_iterator begin() const;
    const_iterator end() const;
    iterator begin();
    iterator end();
};

// still in the .hpp file:
template<typename T>
class IntMatrix::iterator_impl {
public:
    using matrix_type =
        std::conditional_t<
            std::is_const_v<T>,
            const IntMatrix,
            IntMatrix
        >;

private:
    matrix_type* int_matrix;
    size_t index;

    friend IntMatrix;

    iterator_impl(matrix_type* im, size_t idx) :
        int_matrix(im), index(idx)
    {}

public:
    iterator_impl() = default;                          // default constructor
    //iterator_impl(const iterator_impl&) = default;             // not needed
    //iterator_impl &operator=(const iterator_impl &) = default; // not needed
    //~iterator_impl() = default;                                // not needed

    iterator_impl &operator++() {
        ++index;
        return *this;
    }
    iterator_impl operator++(int) {
        iterator_impl old(*this);
        ++index;
        return old;
    }
    bool operator!=(const iterator_impl &it) const {
        return index != it.index || int_matrix != it.int_matrix;
    }
    bool operator==(const iterator_impl &it) const {
        return !(*this != it);
    }

    T& operator*() const {
        return int_matrix->data[index];
    }
};

// in the .cpp file:
IntMatrix::const_iterator IntMatrix::cbegin() const { return {this, 0}; }
IntMatrix::const_iterator IntMatrix::cend() const { return {this, size}; }
IntMatrix::const_iterator IntMatrix::begin() const { return cbegin(); }
IntMatrix::const_iterator IntMatrix::end() const { return cend(); }
IntMatrix::iterator IntMatrix::begin() { return {this, 0}; }
IntMatrix::iterator IntMatrix::end() { return {this, size}; }

演示


編輯:如果Matrix本身是 class 模板,則需要稍微更改迭代器。

#include <cstddef>
#include <type_traits>

// in the .hpp file:
template<typename T>
class Matrix {
private:
    T data[10];       // just an example
    size_t size = 10; // just an example

    template<typename I>
    class iterator_impl;

public:
    // two typedefs using the template:
    using iterator = iterator_impl<T>;
    using const_iterator = iterator_impl<const T>;

    auto cbegin() const;
    auto cend() const;
    auto begin() const;
    auto end() const;
    auto begin();
    auto end();
};

// still in the .hpp file:
template<typename T>
template<typename I>
class Matrix<T>::iterator_impl {
public:
    using value_type = std::remove_const_t<I>;

    using matrix_type =
        std::conditional_t<
            std::is_const_v<I>,
            const Matrix<value_type>,
            Matrix<value_type>
        >;

private:
    matrix_type* matrix;
    size_t index;

    friend Matrix;

    iterator_impl(matrix_type* im, size_t idx) :
        matrix(im), index(idx)
    {}

public:
    iterator_impl() = default;                          // default constructor

    iterator_impl& operator++() {
        ++index;
        return *this;
    }
    iterator_impl operator++(int) {
        iterator_impl old(*this);
        ++index;
        return old;
    }
    bool operator!=(const iterator_impl &it) const {
        return index != it.index || matrix != it.matrix;
    }
    bool operator==(const iterator_impl &it) const {
        return !(*this != it);
    }

    I& operator*() const {
        return matrix->data[index];
    }
};

// still in the .hpp file
template<typename T> auto Matrix<T>::cbegin() const { return const_iterator{this, 0}; }
template<typename T> auto Matrix<T>::cend() const { return const_iterator{this, size}; }
template<typename T> auto Matrix<T>::begin() const { return cbegin(); }
template<typename T> auto Matrix<T>::end() const { return cend(); }
template<typename T> auto Matrix<T>::begin() { return iterator{this, 0}; }
template<typename T> auto Matrix<T>::end() { return iterator{this, size}; }

演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM