std::sort 在我的自定义迭代器上不起作用

std::sort does not work on my custom iterator

本文关键字:迭代器 不起作用 自定义 我的 sort std      更新时间:2023-10-16

我正在使用自己的自定义迭代器实现自己的自定义静态数组容器。由于某种原因,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 时,它无法对容器进行任何更改

这是我的整个数组类:

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);
    }
};

一旦我注释掉operator bool(因为它使某些表达式模棱两可(,并修复后递增和后递减以采用int而不是ptrdiff_t,您的代码就会编译并为我工作。如果存在问题,则可能在于未显示的代码。