// 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 |