-// Copyright (C) 2002 Ronald Garcia
-//
-// Permission to copy, use, sell and distribute this software is granted
-// provided this copyright notice appears in all copies.
-// Permission to modify the code and to distribute modified code is granted
-// provided this copyright notice appears in all copies, and a notice
-// that the code was modified is included with the copyright notice.
-//
-// This software is provided "as is" without express or implied warranty,
-// and with no claim as to its suitability for any purpose.
-//
+// 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
//
#include "boost/multi_array/base.hpp"
-#include "boost/multi_array/iterator_adaptors.hpp"
-#include "boost/iterator_adaptors.hpp"
+#include "boost/iterator/iterator_facade.hpp"
+#include "boost/mpl/aux_/msvc_eti_base.hpp"
+#include <algorithm>
#include <cstddef>
#include <iterator>
// iterator components
/////////////////////////////////////////////////////////////////////////
-template <typename T, typename TPtr>
-struct iterator_base : private multi_array_base {
- typedef multi_array_base super_type;
- typedef super_type::index index;
- typedef super_type::size_type size_type;
+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() {}
- iterator_base(int idx, TPtr base, const size_type* extents,
+ 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) {
+ 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());
}
+
- template <typename OPtr>
- iterator_base(const iterator_base<T,OPtr>& rhs) :
- idx_(rhs.idx_), base_(rhs.base_), extents_(rhs.extents_),
- strides_(rhs.strides_), index_base_(rhs.index_base_) {
- }
-
- // default constructor required
- iterator_base() {}
-};
-
-template<typename T, std::size_t NumDims>
-struct iterator_policies :
- public boost::detail::multi_array::default_iterator_policies,
- private value_accessor_generator<T,NumDims>::type {
-private:
- typedef typename value_accessor_generator<T,NumDims>::type super_type;
-public:
- template <class IteratorAdaptor>
- typename IteratorAdaptor::reference
- dereference(const IteratorAdaptor& iter) const {
- typedef typename IteratorAdaptor::reference reference;
- return super_type::access(boost::type<reference>(),
- iter.base().idx_,
- iter.base().base_,
- iter.base().extents_,
- iter.base().strides_,
- iter.base().index_base_);
+ reference dereference() const
+ {
+ typedef typename value_accessor_generator<T,NumDims>::type accessor;
+ return accessor::access(boost::type<reference>(),
+ idx_,
+ base_,
+ extents_,
+ strides_,
+ index_base_);
}
- template <class IteratorAdaptor>
- static void increment(IteratorAdaptor& x) { ++x.base().idx_; }
+ void increment() { ++idx_; }
+ void decrement() { --idx_; }
template <class IteratorAdaptor>
- static void decrement(IteratorAdaptor& x) { --x.base().idx_; }
-
- template <class IteratorAdaptor1, class IteratorAdaptor2>
- bool equal(IteratorAdaptor1& lhs, IteratorAdaptor2& rhs) const {
- return (lhs.base().idx_ == rhs.base().idx_) &&
- (lhs.base().base_ == rhs.base().base_) &&
- (lhs.base().extents_ == rhs.base().extents_) &&
- (lhs.base().strides_ == rhs.base().strides_) &&
- (lhs.base().index_base_ == rhs.base().index_base_);
+ 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 IteratorAdaptor, class DifferenceType>
- static void advance(IteratorAdaptor& x, DifferenceType n) {
- x.idx_ += n;
+ template <class DifferenceType>
+ void advance(DifferenceType n) {
+ idx_ += n;
}
- template <class IteratorAdaptor1, class IteratorAdaptor2>
- typename IteratorAdaptor1::difference_type
- distance(IteratorAdaptor1& lhs, IteratorAdaptor2& rhs) const {
- return rhs.base().idx_ - lhs.base().idx_;
+ template <class IteratorAdaptor>
+ typename facade_type::difference_type
+ distance_to(IteratorAdaptor& rhs) const {
+ return rhs.idx_ - idx_;
}
-};
-
-
-template <typename T, typename base_type,
- std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct iterator_gen_helper {
-private:
- typedef iterator_policies<T,NumDims> policies;
- typedef value_type* pointer_type;
- typedef tag category;
-public:
- typedef boost::detail::multi_array::iterator_adaptor<base_type,policies,value_type,
- reference_type,pointer_type,category,difference_type> type;
-};
-
-
-template <typename T, std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct iterator_generator {
-private:
- typedef iterator_base<T,T*> base_type;
-public:
- typedef typename iterator_gen_helper<T,base_type,NumDims,value_type,
- reference_type,tag,difference_type>::type type;
-};
-
-template <typename T, std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct const_iterator_generator {
-private:
- typedef iterator_base<T,const T*> base_type;
-public:
- typedef typename iterator_gen_helper<T,base_type,NumDims,value_type,
- reference_type,tag,difference_type>::type type;
-};
-template <typename T, std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct reverse_iterator_generator {
-private:
- typedef iterator_base<T,T*> base_type;
- typedef typename iterator_gen_helper<T,base_type,NumDims,value_type,
- reference_type,tag,difference_type>::type it_type;
-public:
- typedef typename boost::reverse_iterator_generator<it_type>::type type;
-};
-template <typename T, std::size_t NumDims, typename value_type,
- typename reference_type, typename tag, typename difference_type>
-struct const_reverse_iterator_generator {
-private:
- typedef iterator_base<T,const T*> base_type;
- typedef typename iterator_gen_helper<T,base_type,NumDims,value_type,
- reference_type,tag,difference_type>::type it_type;
-public:
- typedef typename boost::reverse_iterator_generator<it_type>::type type;
};
} // namespace multi_array