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