Skip to content
multi_span 78.2 KiB
Newer Older
{
    using Base = std::iterator<std::random_access_iterator_tag, typename Span::value_type>;

public:
    using typename Base::reference;
    using typename Base::pointer;
    using typename Base::difference_type;

private:
    template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
    friend class multi_span;

    pointer data_;
    const Span* m_validator;
    void validateThis() const
    {
        // iterator is out of range of the array
        Expects(data_ >= m_validator->data_ && data_ < m_validator->data_ + m_validator->size());
    }
    contiguous_span_iterator(const Span* container, bool isbegin)
        : data_(isbegin ? container->data_ : container->data_ + container->size())
        , m_validator(container)
    {
    }

public:
    reference operator*() const noexcept
    {
        validateThis();
        return *data_;
    }
    pointer operator->() const noexcept
    {
        validateThis();
        return data_;
    }
    contiguous_span_iterator& operator++() noexcept
    {
        ++data_;
        return *this;
    }
    contiguous_span_iterator operator++(int) noexcept
    {
        auto ret = *this;
        ++(*this);
        return ret;
    }
    contiguous_span_iterator& operator--() noexcept
    {
        --data_;
        return *this;
    }
    contiguous_span_iterator operator--(int) noexcept
    {
        auto ret = *this;
        --(*this);
        return ret;
    }
    contiguous_span_iterator operator+(difference_type n) const noexcept
    {
        contiguous_span_iterator ret{*this};
        return ret += n;
    }
    contiguous_span_iterator& operator+=(difference_type n) noexcept
    {
        data_ += n;
        return *this;
    }
    contiguous_span_iterator operator-(difference_type n) const noexcept
    {
        contiguous_span_iterator ret{*this};
        return ret -= n;
    }
    contiguous_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; }
    difference_type operator-(const contiguous_span_iterator& rhs) const noexcept
    {
        Expects(m_validator == rhs.m_validator);
        return data_ - rhs.data_;
    }
    reference operator[](difference_type n) const noexcept { return *(*this + n); }
    bool operator==(const contiguous_span_iterator& rhs) const noexcept
    {
        Expects(m_validator == rhs.m_validator);
        return data_ == rhs.data_;
    }
    bool operator!=(const contiguous_span_iterator& rhs) const noexcept { return !(*this == rhs); }
    bool operator<(const contiguous_span_iterator& rhs) const noexcept
    {
        Expects(m_validator == rhs.m_validator);
        return data_ < rhs.data_;
    }
    bool operator<=(const contiguous_span_iterator& rhs) const noexcept { return !(rhs < *this); }
    bool operator>(const contiguous_span_iterator& rhs) const noexcept { return rhs < *this; }
    bool operator>=(const contiguous_span_iterator& rhs) const noexcept { return !(rhs > *this); }
    void swap(contiguous_span_iterator& rhs) noexcept
    {
        std::swap(data_, rhs.data_);
        std::swap(m_validator, rhs.m_validator);
    }
};

template <typename Span>
contiguous_span_iterator<Span> operator+(typename contiguous_span_iterator<Span>::difference_type n,
                                         const contiguous_span_iterator<Span>& rhs) noexcept
{
    return rhs + n;
}

template <typename Span>
class general_span_iterator
    : public std::iterator<std::random_access_iterator_tag, typename Span::value_type>
{
    using Base = std::iterator<std::random_access_iterator_tag, typename Span::value_type>;

public:
    using typename Base::reference;
    using typename Base::pointer;
    using typename Base::difference_type;
    using typename Base::value_type;

private:
    template <typename ValueType, size_t Rank>
    friend class strided_span;

    const Span* m_container;
    typename Span::bounds_type::iterator m_itr;
    general_span_iterator(const Span* container, bool isbegin)
        : m_container(container)
        , m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end())
    {
    }

public:
    reference operator*() noexcept { return (*m_container)[*m_itr]; }
    pointer operator->() noexcept { return &(*m_container)[*m_itr]; }
    general_span_iterator& operator++() noexcept
    {
        ++m_itr;
        return *this;
    }
    general_span_iterator operator++(int) noexcept
    {
        auto ret = *this;
        ++(*this);
        return ret;
    }
    general_span_iterator& operator--() noexcept
    {
        --m_itr;
        return *this;
    }
    general_span_iterator operator--(int) noexcept
    {
        auto ret = *this;
        --(*this);
        return ret;
    }
    general_span_iterator operator+(difference_type n) const noexcept
    {
        general_span_iterator ret{*this};
        return ret += n;
    }
    general_span_iterator& operator+=(difference_type n) noexcept
    {
        m_itr += n;
        return *this;
    }
    general_span_iterator operator-(difference_type n) const noexcept
    {
        general_span_iterator ret{*this};
        return ret -= n;
    }
    general_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; }
    difference_type operator-(const general_span_iterator& rhs) const noexcept
    {
        Expects(m_container == rhs.m_container);
        return m_itr - rhs.m_itr;
    }
    value_type operator[](difference_type n) const noexcept { return (*m_container)[m_itr[n]]; }

    bool operator==(const general_span_iterator& rhs) const noexcept
    {
        Expects(m_container == rhs.m_container);
        return m_itr == rhs.m_itr;
    }
    bool operator!=(const general_span_iterator& rhs) const noexcept { return !(*this == rhs); }
    bool operator<(const general_span_iterator& rhs) const noexcept
    {
        Expects(m_container == rhs.m_container);
        return m_itr < rhs.m_itr;
    }
    bool operator<=(const general_span_iterator& rhs) const noexcept { return !(rhs < *this); }
    bool operator>(const general_span_iterator& rhs) const noexcept { return rhs < *this; }
    bool operator>=(const general_span_iterator& rhs) const noexcept { return !(rhs > *this); }
    void swap(general_span_iterator& rhs) noexcept
    {
        std::swap(m_itr, rhs.m_itr);
        std::swap(m_container, rhs.m_container);
    }
};

template <typename Span>
general_span_iterator<Span> operator+(typename general_span_iterator<Span>::difference_type n,
                                      const general_span_iterator<Span>& rhs) noexcept
{
    return rhs + n;
}

} // namespace gsl

#ifdef _MSC_VER

#undef constexpr
#pragma pop_macro("constexpr")

#if _MSC_VER <= 1800
#pragma warning(pop)

#ifndef GSL_THROW_ON_CONTRACT_VIOLATION
#undef noexcept
#pragma pop_macro("noexcept")
#endif // GSL_THROW_ON_CONTRACT_VIOLATION

#undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG

#endif // _MSC_VER <= 1800

#endif // _MSC_VER

#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)

#undef noexcept

#ifdef _MSC_VER
#pragma warning(pop)
#pragma pop_macro("noexcept")
#endif

#endif // GSL_THROW_ON_CONTRACT_VIOLATION

#endif // GSL_MULTI_SPAN_H