std :: sort无法在我的自定义迭代器上运行

时间:2019-06-18 02:23:42

标签: c++ iterator

我正在使用自己的自定义迭代器实现自己的自定义静态数组容器。由于某种原因,尽管程序成功编译,std :: sort仍未对我的容器产生预期的作用

我相信我已经实现了所有必要的迭代器方法

    template<typename T>
    class ArrayIterator : public std::iterator<std::random_access_iterator_tag, T, std::ptrdiff_t, T*, T&> {
    private:
        T* m_frontPointer;
        T* m_backPointer;
        T* m_currentPointer;

        void _checkRange(const std::ptrdiff_t movement) const {
            const T* destination = m_currentPointer + movement;

            if (destination < m_frontPointer || destination > m_backPointer) {
                throw std::out_of_range("iterator out of range");
            }
        }

        void _checkPosition(void) const {
            if (m_currentPointer < m_frontPointer || m_currentPointer >= m_backPointer) {
                throw std::logic_error("iterator out of range");
            }
        }

    public:
        ArrayIterator(T* frontPointer, T* backPointer, T* currentPointer) {
            m_frontPointer = frontPointer;
            m_backPointer = backPointer;
            m_currentPointer = currentPointer;
        }

        ~ArrayIterator(void) {
        }

        operator ArrayIterator<const T>(void) const {
            return ArrayIterator<const T>(m_frontPointer, m_backPointer, m_currentPointer);
        }

        operator bool(void) const {
            m_currentPointer != nullptr;
        }

        ArrayIterator<T>& operator=(const ArrayIterator<T>& iter) {
            m_frontPointer = iter.m_frontPointer;
            m_backPointer = iter.m_backPointer;
            m_currentPointer = iter.m_currentPointer;

            return *this;
        }

        ArrayIterator<T>& operator+=(const std::ptrdiff_t movement) {
            this->_checkRange(movement);
            m_currentPointer += movement;

            return *this;
        }

        ArrayIterator<T>& operator-=(const std::ptrdiff_t movement) {
            this->_checkRange(-movement);
            m_currentPointer -= movement;

            return *this;
        }

        ArrayIterator<T>& operator++(void) {
            this->_checkRange(1);
            ++m_currentPointer;

            return *this;
        }

        ArrayIterator<T>& operator--(void) {
            this->_checkRange(-1);
            --m_currentPointer;

            return *this;
        }

        ArrayIterator<T> operator++(std::ptrdiff_t) {
            this->_checkRange(1);

            ArrayIterator<T> iter(m_frontPointer, m_backPointer, m_currentPointer);
            ++m_currentPointer;

            return iter;
        }

        ArrayIterator<T> operator--(std::ptrdiff_t) {
            this->_checkRange(-1);

            ArrayIterator<T> iter(m_frontPointer, m_backPointer, m_currentPointer);
            --m_currentPointer;

            return iter;
        }

        ArrayIterator<T> operator+(const std::ptrdiff_t movement) const {
            this->_checkRange(movement);

            return ArrayIterator(m_frontPointer, m_backPointer, m_currentPointer + movement);
        }

        friend ArrayIterator<T> operator+(const std::ptrdiff_t movement, const ArrayIterator<T>& iter) {
            iter._checkRange(movement);

            return ArrayIterator(iter.m_frontPointer, iter.m_backPointer, iter.m_currentPointer + movement);
        }

        ArrayIterator<T> operator-(const std::ptrdiff_t movement) const {
            this->_checkRange(-movement);

            return ArrayIterator(m_frontPointer, m_backPointer, m_currentPointer - movement);
        }

        std::ptrdiff_t operator-(const ArrayIterator<T>& iter) const {
            return std::distance(m_currentPointer, iter.m_currentPointer);
        }

        std::ptrdiff_t operator-(ArrayIterator<const T>& iter) const {
            return std::distance(m_currentPointer, iter.m_currentPointer);
        }

        T& operator*(void) {
            this->_checkPosition();
            return *(m_currentPointer);
        }

        const T& operator*(void) const {
            this->_checkPosition();
            return *(m_currentPointer);
        }

        T* operator->(void) {
            this->_checkPosition();
            return m_currentPointer;
        }

        const T* operator->(void) const {
            this->_checkPosition();
            return m_currentPointer;
        }

        bool operator==(const ArrayIterator<T>& iter) const {
            return m_frontPointer == iter.m_frontPointer &&
                m_backPointer == iter.m_backPointer &&
                m_currentPointer == iter.m_currentPointer;
        }

        bool operator!=(const ArrayIterator<T>& iter) const {
            return !(*this == iter);
        }

        bool operator<(const ArrayIterator<T>& iter) const {
            return m_currentPointer < iter.m_currentPointer;
        }

        bool operator>(const ArrayIterator<T>& iter) const {
            return m_currentPointer > iter.m_currentPointer;
        }

        bool operator<=(const ArrayIterator<T>& iter) const {
            return m_currentPointer <= iter.m_currentPointer;
        }

        bool operator>=(const ArrayIterator<T>& iter) const {
            return m_currentPointer >= iter.m_currentPointer;
        }
    };

由于某种原因,当调用std :: sort时,它无法对容器进行任何更改

这是我的整个Array类:

template<typename E, std::size_t Size>
class Array {
private:
    template<typename T>
    class _ArrayIterator {
    private:
        T* m_frontPointer;
        T* m_backPointer;
        T* m_currentPointer;

        void _checkRange(const std::ptrdiff_t movement) const {
            const T* destination = m_currentPointer + movement;

            if (destination < m_frontPointer || destination > m_backPointer) {
                throw std::out_of_range("iterator out of range");
            }
        }

        void _checkPosition(void) const {
            if (m_currentPointer < m_frontPointer || m_currentPointer > m_backPointer) {
                throw std::logic_error("iterator out of range");
            }
        }

    public:
        using iterator_category = std::random_access_iterator_tag;
        using value_type = T;
        using difference_type = std::ptrdiff_t;
        using pointer = T*;
        using reference = E&;


        _ArrayIterator(T* frontPointer = nullptr, T* backPointer = nullptr, T* currentPointer = nullptr) {
            m_frontPointer = frontPointer;
            m_backPointer = backPointer;
            m_currentPointer = currentPointer;
        }

        _ArrayIterator(const _ArrayIterator<T>& iter) {
            m_frontPointer = iter.m_frontPointer;
            m_backPointer = iter.m_backPointer;
            m_currentPointer = iter.m_currentPointer;
        }

        ~_ArrayIterator(void) {
        }

        operator _ArrayIterator<const T>(void) const {
            return _ArrayIterator<const T>(m_frontPointer, m_backPointer, m_currentPointer);
        }

        _ArrayIterator<T>& operator=(const _ArrayIterator<T>& iter) {
            m_frontPointer = iter.m_frontPointer;
            m_backPointer = iter.m_backPointer;
            m_currentPointer = iter.m_currentPointer;

            return *this;
        }

        _ArrayIterator<T>& operator+=(const std::ptrdiff_t movement) {
            this->_checkRange(movement);
            m_currentPointer += movement;

            return *this;
        }

        _ArrayIterator<T>& operator-=(const std::ptrdiff_t movement) {
            this->_checkRange(-movement);
            m_currentPointer -= movement;

            return *this;
        }

        _ArrayIterator<T>& operator++(void) {
            this->_checkRange(1);
            ++m_currentPointer;

            return *this;
        }

        _ArrayIterator<T>& operator--(void) {
            this->_checkRange(-1);
            --m_currentPointer;

            return *this;
        }

        _ArrayIterator<T> operator++(std::ptrdiff_t) {
            this->_checkRange(1);

            _ArrayIterator<T> iter(m_frontPointer, m_backPointer, m_currentPointer);
            ++m_currentPointer;

            return iter;
        }

        _ArrayIterator<T> operator--(std::ptrdiff_t) {
            this->_checkRange(-1);

            _ArrayIterator<T> iter(m_frontPointer, m_backPointer, m_currentPointer);
            --m_currentPointer;

            return iter;
        }

        _ArrayIterator<T> operator+(const std::ptrdiff_t movement) const {
            this->_checkRange(movement);

            return _ArrayIterator(m_frontPointer, m_backPointer, m_currentPointer + movement);
        }

        friend _ArrayIterator<T> operator+(const std::ptrdiff_t movement, const _ArrayIterator<T>& iter) {
            iter._checkRange(movement);

            return _ArrayIterator(iter.m_frontPointer, iter.m_backPointer, iter.m_currentPointer + movement);
        }

        _ArrayIterator<T> operator-(const std::ptrdiff_t movement) const {
            this->_checkRange(-movement);

            return _ArrayIterator(m_frontPointer, m_backPointer, m_currentPointer - movement);
        }

        std::ptrdiff_t operator-(const _ArrayIterator<T>& iter) const {
            return std::distance(m_currentPointer, iter.m_currentPointer);
        }

        std::ptrdiff_t operator-(_ArrayIterator<const T>& iter) const {
            return std::distance(m_currentPointer, iter.m_currentPointer);
        }

        T& operator*(void) {
            this->_checkPosition();
            return *m_currentPointer;
        }

        const T& operator*(void) const {
            this->_checkPosition();
            return *m_currentPointer;
        }

        T& operator[](const std::ptrdiff_t movement) {
            this->_checkRange(movement);
            return *m_currentPointer;
        }

        const T& operator[](const std::ptrdiff_t movement) const {
            this->_checkRange(movement);
            return *m_currentPointer;
        }

        T* operator->(void) {
            this->_checkPosition();
            return m_currentPointer;
        }

        const T* operator->(void) const {
            this->_checkPosition();
            return m_currentPointer;
        }

        bool operator==(const _ArrayIterator<T>& iter) const {
            return m_frontPointer == iter.m_frontPointer &&
                   m_backPointer == iter.m_backPointer &&
                   m_currentPointer == iter.m_currentPointer;
        }

        bool operator!=(const _ArrayIterator<T>& iter) const {
            return !(*this == iter);
        }

        bool operator<(const _ArrayIterator<T>& iter) const {
            return m_currentPointer < iter.m_currentPointer;
        }

        bool operator>(const _ArrayIterator<T>& iter) const {
            return m_currentPointer > iter.m_currentPointer;
        }

        bool operator<=(const _ArrayIterator<T>& iter) const {
            return m_currentPointer <= iter.m_currentPointer;
        }

        bool operator>=(const _ArrayIterator<T>& iter) const {
            return m_currentPointer >= iter.m_currentPointer;
        }
    };


    E* m_elementData;

public:
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using value_type = E;
    using reference = E&;
    using const_reference = const E&;
    using pointer = E*;
    using const_pointer = const E*;
    using iterator = _ArrayIterator<E>;
    using const_iterator = _ArrayIterator<const E>;
    /*using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;*/


    Array(void) {
        m_elementData = new E[Size];
    }

    Array(const Array<E, Size>& arr) : Array() {
        for (std::size_t index = 0; index < Size; ++index) {
            m_elementData[index] = arr.m_elementData[index];
        }
    }

    Array(Array<E, Size>&& arr) : Array() {
        for (std::size_t index = 0; index < Size; ++index) {
            m_elementData[index] = std::move(arr.m_elementData[index]);
        }
    }

    Array(std::initializer_list<E> initList) : Array() {
        typename std::initializer_list<E>::iterator iter = initList.begin();
        std::size_t index = 0;

        while (iter != initList.end()) {
            m_elementData[index] = *iter;

            ++index;
            ++iter;
        }
    }

    ~Array(void) {
        delete[] m_elementData;
    }

    std::size_t size(void) const noexcept {
        return Size;
    }

    std::size_t maxSize(void) const noexcept {
        return Size;
    }

    bool empty(void) const noexcept {
        return Size == 0;
    }

    E& at(const std::size_t index) {
        if (index >= Size) {
            throw std::out_of_range("index out of bounds");
        }

        return m_elementData[index];
    }

    const E& at(const std::size_t index) const {
        if (index >= Size) {
            throw std::out_of_range("index out of bounds");
        }

        return m_elementData[index];
    }

    E& operator[](const std::size_t index) {
        return this->at(index);
    }

    const E& operator[](const std::size_t index) const {
        return this->at(index);
    }

    E& front(void) {
        return this->at(0);
    }

    const E& front(void) const {
        return this->at(0);
    }

    E& back(void) {
        return this->at(Size - 1);
    }

    const E& back(void) const {
        return this->at(Size - 1);
    }

    E* data(void) noexcept {
        return m_elementData;
    }

    const E* data(void) const noexcept {
        return m_elementData;
    }

    void fill(const E& value) {
        algorithm::fill(this->begin(), this->end(), value);
    }

    void swap(Array<E, Size>& arr) {
        E* copy = m_elementData;
        m_elementData = arr.m_elementData;
        arr.m_elementData = copy;
    }


    template<typename T>
    std::ptrdiff_t indexOf(const T& element, const std::ptrdiff_t fromIndex = 0) const {
        for (std::ptrdiff_t index = fromIndex; index < Size; ++index) {
            if (element == m_elementData[index]) {
                return index;
            }
        }

        return -1;
    }

    template<typename T>
    std::ptrdiff_t lastIndexOf(const T& element, const std::ptrdiff_t fromIndex = Size - 1) const {
        for (std::ptrdiff_t index = fromIndex; index >= 0; --index) {
            if (element == m_elementData[index]) {
                return index;
            }
        }

        return -1;
    }

    template<typename T>
    bool contains(const T& element) {
        return this->indexOf(element) != -1;
    }

    void reverse(void) {
        algorithm::reverse(this->begin(), this->end());
    }

    void sort(void) {
        algorithm::sort(this->begin(), this->end());
    }

    template<typename Comparer>
    void sort(Comparer comp) {
        algorithm::sort(this->begin(), this->end(), comp);
    }

    template<std::size_t N>
    Array<E, (N + Size)> concat(const Array<E, N>& arr) const {
        Array<E, (N + Size)> concatArr;
        algorithm::concat(this->begin(), this->end(), arr.begin(), arr.end(), concatArr.begin());

        return concatArr;
    }

    /*template<std::size_t N>
    friend Array<E, (N + Size)> concat(Array<E, Size>&& left, Array<E, N>&& right) {
        Array<E, (N + Size)> concatArr;
        algorithm::concat(
            std::make_move_iterator(left.begin()), 
            std::make_move_iterator(left.end()), 
            std::make_move_iterator(right.begin()), 
            std::make_move_iterator(right.end()), 
            concatArr
        );

        return concatArr;
    }*/

    template<std::size_t N>
    Array<E, (N + Size)> merge(const Array<E, N>& arr) const {
        Array<E, (N + Size)> mergeArr;
        algorithm::merge(this->begin(), this->end(), arr.begin(), arr.end(), mergeArr.begin());

        return mergeArr;
    }

    template<std::size_t N, typename Comparer>
    Array<E, (N + Size)> merge(const Array<E, N>& arr, Comparer comp) const {
        Array<E, (N + Size)> mergeArr;
        algorithm::merge(this->begin(), this->end(), arr.begin(), arr.end(), mergeArr.begin(), comp);

        return mergeArr;
    }

    /*template<std::size_t N>
    friend Array<E, (N + Size)> merge(Array<E, Size>&& left, Array<E, N>&& right) {
        Array<E, (N + Size)> mergeArr;
        algorithm::merge(
            std::make_move_iterator(left.begin()), 
            std::make_move_iterator(left.end()), 
            std::make_move_iterator(right.begin()), 
            std::make_move_iterator(right.end()), 
            mergeArr.begin()
        );

        return mergeArr;
    }

    template<std::size_t N, typename Comparer>
    friend Array<E, (N + Size)> merge(Array<E, Size>&& left, Array<E, N>&& right, Comparer comp) {
        Array<E, (N + Size)> mergeArr;
        algorithm::merge(
            std::make_move_iterator(left.begin()), 
            std::make_move_iterator(left.end()), 
            std::make_move_iterator(right.begin()), 
            std::make_move_iterator(right.end()), 
            mergeArr.begin(), 
            comp
        );

        return mergeArr;
    }*/

    void rotateRight(void) {
        algorithm::rotate(this->begin(), this->end());
    }

    /*void rotateLeft(void) {
        algorithm::rotate(this->rbegin(), this->rend());
    }*/

    void shuffle(void) {
        this->shuffle([](std::size_t bound) { return std::rand() % bound; });
    }

    template<typename RandomNumberGen>
    void shuffle(RandomNumberGen&& generator) {
        std::srand(std::time(0));
        algorithm::shuffle(this->begin(), this->end(), generator);
    }

    iterator begin(void) noexcept {
        return iterator(m_elementData, m_elementData + Size, m_elementData);
    }

    const_iterator begin(void) const noexcept {
        return const_iterator(m_elementData, m_elementData + Size, m_elementData);
    }

    iterator end(void) noexcept {
        return iterator(m_elementData, m_elementData + Size, m_elementData + Size);
    }

    const_iterator end(void) const noexcept {
        return const_iterator(m_elementData, m_elementData + Size, m_elementData + Size);
    }

    /*reverse_iterator rbegin(void) noexcept {
        return reverse_iterator(m_elementData - 1, m_elementData + Size - 1, m_elementData + Size - 1);
    }

    const_reverse_iterator rbegin(void) const noexcept {
        return const_reverse_iterator(m_elementData - 1, m_elementData + Size - 1, m_elementData + Size - 1);
    }

    reverse_iterator rend(void) noexcept {
        return reverse_iterator(m_elementData - 1, m_elementData + Size - 1, m_elementData - 1);
    }

    const_reverse_iterator rend(void) const noexcept {
        return const_reverse_iterator(m_elementData - 1, m_elementData + Size - 1, m_elementData - 1);
    }*/

    const_iterator cbegin(void) const noexcept {
        return const_iterator(m_elementData, m_elementData + Size, m_elementData);
    }

    const_iterator cend(void) const noexcept {
        return const_iterator(m_elementData, m_elementData + Size, m_elementData + Size);
    }

    /*const_reverse_iterator crbegin(void) const noexcept {
        return const_reverse_iterator(m_elementData - 1, m_elementData + Size - 1, m_elementData + Size - 1);
    }

    const_reverse_iterator crend(void) const noexcept {
        return const_reverse_iterator(m_elementData - 1, m_elementData + Size - 1, m_elementData - 1);
    }*/

    template<typename T>
    bool operator==(const Array<T, Size>& arr) const {
        for (std::size_t index = 0; index < this->size(); index++) {
            if (m_elementData[index] == arr.m_elementData[index]) {
                return false;
            }
        }

        return true;
    }

    template<typename T>
    bool operator!=(const Array<T, Size>& arr) const {
        return !(*this == arr);
    }

    template<typename T>
    bool operator<(const Array<T, Size>& arr) const {
        for (std::size_t index = 0; index < this->size(); index++) {
            if (m_elementData[index] < arr.m_elementData[index]) {
                return true;
            }

            if (m_elementData[index] > arr.m_elementData[index]) {
                return false;
            }
        }

        return false;
    }

    template<typename T>
    bool operator>(const Array<T, Size>& arr) const {
        return arr < *this;
    }

    template<typename T>
    bool operator<=(const Array<T, Size>& arr) const {
        return !(*this > arr);
    }

    template<typename T>
    bool operator>=(const Array<T, Size>& arr) const {
        return !(*this < arr);
    }
};

1 个答案:

答案 0 :(得分:0)

一旦我注释掉operator bool(因为它使某些表达式变得模棱两可),并修复了后递增和后递减采取int而不是ptrdiff_tyour code compiles and works for me 。在某种程度上说,有问题可能在于未显示的代码。