| // Copyright 2002 The Trustees of Indiana University. |
| |
| // Use, modification and distribution is subject to the Boost Software |
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| // Boost.MultiArray Library |
| // Authors: Ronald Garcia |
| // Jeremy Siek |
| // Andrew Lumsdaine |
| // See http://www.boost.org/libs/multi_array for documentation. |
| |
| #ifndef ITERATOR_RG071801_HPP |
| #define ITERATOR_RG071801_HPP |
| |
| // |
| // iterator.hpp - implementation of iterators for the |
| // multi-dimensional array class |
| // |
| |
| #include "boost/multi_array/base.hpp" |
| #include "boost/iterator/iterator_facade.hpp" |
| #include "boost/mpl/aux_/msvc_eti_base.hpp" |
| #include <algorithm> |
| #include <cstddef> |
| #include <iterator> |
| |
| namespace boost { |
| namespace detail { |
| namespace multi_array { |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // iterator components |
| ///////////////////////////////////////////////////////////////////////// |
| |
| template <class T> |
| struct operator_arrow_proxy |
| { |
| operator_arrow_proxy(T const& px) : value_(px) {} |
| T* operator->() const { return &value_; } |
| // This function is needed for MWCW and BCC, which won't call operator-> |
| // again automatically per 13.3.1.2 para 8 |
| operator T*() const { return &value_; } |
| mutable T value_; |
| }; |
| |
| template <typename T, typename TPtr, typename NumDims, typename Reference> |
| class array_iterator; |
| |
| template <typename T, typename TPtr, typename NumDims, typename Reference> |
| class array_iterator |
| : public |
| iterator_facade< |
| array_iterator<T,TPtr,NumDims,Reference> |
| , typename associated_types<T,NumDims>::value_type |
| , boost::random_access_traversal_tag |
| , Reference |
| > |
| , private |
| #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
| mpl::aux::msvc_eti_base<typename |
| #endif |
| value_accessor_generator<T,NumDims>::type |
| #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
| >::type |
| #endif |
| { |
| friend class iterator_core_access; |
| typedef detail::multi_array::associated_types<T,NumDims> access_t; |
| |
| typedef iterator_facade< |
| array_iterator<T,TPtr,NumDims,Reference> |
| , typename detail::multi_array::associated_types<T,NumDims>::value_type |
| , boost::random_access_traversal_tag |
| , Reference |
| > facade_type; |
| |
| typedef typename access_t::index index; |
| typedef typename access_t::size_type size_type; |
| |
| #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
| template <typename, typename, typename, typename> |
| friend class array_iterator; |
| #else |
| public: |
| #endif |
| |
| index idx_; |
| TPtr base_; |
| const size_type* extents_; |
| const index* strides_; |
| const index* index_base_; |
| |
| public: |
| // Typedefs to circumvent ambiguities between parent classes |
| typedef typename facade_type::reference reference; |
| typedef typename facade_type::value_type value_type; |
| typedef typename facade_type::difference_type difference_type; |
| |
| array_iterator() {} |
| |
| array_iterator(index idx, TPtr base, const size_type* extents, |
| const index* strides, |
| const index* index_base) : |
| idx_(idx), base_(base), extents_(extents), |
| strides_(strides), index_base_(index_base) { } |
| |
| template <typename OPtr, typename ORef> |
| array_iterator( |
| const array_iterator<T,OPtr,NumDims,ORef>& rhs |
| , typename boost::enable_if_convertible<OPtr,TPtr>::type* = 0 |
| ) |
| : idx_(rhs.idx_), base_(rhs.base_), extents_(rhs.extents_), |
| strides_(rhs.strides_), index_base_(rhs.index_base_) { } |
| |
| |
| // RG - we make our own operator-> |
| operator_arrow_proxy<reference> |
| operator->() const |
| { |
| return operator_arrow_proxy<reference>(this->dereference()); |
| } |
| |
| |
| reference dereference() const |
| { |
| typedef typename value_accessor_generator<T,NumDims>::type accessor; |
| return accessor::access(boost::type<reference>(), |
| idx_, |
| base_, |
| extents_, |
| strides_, |
| index_base_); |
| } |
| |
| void increment() { ++idx_; } |
| void decrement() { --idx_; } |
| |
| template <class IteratorAdaptor> |
| bool equal(IteratorAdaptor& rhs) const { |
| const std::size_t N = NumDims::value; |
| return (idx_ == rhs.idx_) && |
| (base_ == rhs.base_) && |
| ( (extents_ == rhs.extents_) || |
| std::equal(extents_,extents_+N,rhs.extents_) ) && |
| ( (strides_ == rhs.strides_) || |
| std::equal(strides_,strides_+N,rhs.strides_) ) && |
| ( (index_base_ == rhs.index_base_) || |
| std::equal(index_base_,index_base_+N,rhs.index_base_) ); |
| } |
| |
| template <class DifferenceType> |
| void advance(DifferenceType n) { |
| idx_ += n; |
| } |
| |
| template <class IteratorAdaptor> |
| typename facade_type::difference_type |
| distance_to(IteratorAdaptor& rhs) const { |
| return rhs.idx_ - idx_; |
| } |
| |
| |
| }; |
| |
| } // namespace multi_array |
| } // namespace detail |
| } // namespace boost |
| |
| #endif // ITERATOR_RG071801_HPP |