Go to the documentation of this file.00001 #ifndef OPENTISSUE_UTILITY_UTILITY_INDEX_ITERATOR_H
00002 #define OPENTISSUE_UTILITY_UTILITY_INDEX_ITERATOR_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 # include <boost/iterator/iterator_facade.hpp>
00013
00014 # ifndef BOOST_NO_SFINAE
00015 # include <boost/type_traits/is_convertible.hpp>
00016 # include <boost/utility/enable_if.hpp>
00017 # endif
00018
00019 #include <cassert>
00020
00021 namespace OpenTissue
00022 {
00023 namespace utility
00024 {
00025
00031 template <typename index_type, class container_type>
00032 class IndexIterator
00033 : public boost::iterator_facade<
00034 IndexIterator<index_type,container_type>
00035 , typename container_type::value_type
00036 , boost::forward_traversal_tag
00037 >
00038 {
00039 public:
00040
00041 # ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
00042 public:
00043 # else
00044 private:
00045 template <typename, class> friend class IndexIterator;
00046 # endif
00047
00048 bool m_valid;
00049 index_type m_idx;
00050 container_type* m_container;
00051
00052 private:
00053
00054 struct enabler {};
00055
00056 public:
00057 typedef typename container_type::value_type value_type;
00058
00059 IndexIterator()
00060 : m_valid(false)
00061 , m_idx()
00062 , m_container(0)
00063 {}
00064
00065 explicit IndexIterator(container_type const & container, index_type const & idx)
00066 : m_valid(true)
00067 , m_idx(idx)
00068 , m_container(const_cast<container_type*>( &container) )
00069 {}
00070
00071 explicit IndexIterator(container_type const & container )
00072 : m_valid(true)
00073 , m_idx(0)
00074 , m_container(const_cast<container_type*>( &container) )
00075 {}
00076
00077 template <typename other_idx, class other_container>
00078 IndexIterator(
00079 IndexIterator<other_idx,other_container> const& other
00080 # ifndef BOOST_NO_SFINAE
00081 , typename boost::enable_if<
00082 boost::is_convertible<other_container, container_type>
00083 , enabler
00084 >::type = enabler()
00085 # endif
00086 )
00087 : m_valid(other.m_valid)
00088 , m_idx(other.m_idx)
00089 , m_container(other.m_container)
00090 {}
00091
00092
00093 # if !BOOST_WORKAROUND(__GNUC__, == 2)
00094 private:
00095 friend class boost::iterator_core_access;
00096 # endif
00097
00098 template <typename other_idx, class other_container>
00099 bool equal(IndexIterator<other_idx,other_container> const& other) const
00100 {
00101 return (this->m_valid == other.m_valid) &&
00102 (this->m_idx == other.m_idx) &&
00103 (this->m_container == other.m_container);
00104 }
00105
00106 void increment()
00107 {
00108 if(!this->m_valid)
00109 throw std::logic_error("IndexIterator::increment(): can not increment an invalid iterator");
00110 if(this->m_idx >= this->m_container->size())
00111 throw std::out_of_range("IndexIterator::increment(): can not increment past the end");
00112 ++m_idx;
00113 }
00114
00115 bool valid() const
00116 {
00117 return m_valid;
00118 }
00119
00120 value_type & dereference() const
00121 {
00122 if(!this->m_valid)
00123 throw std::logic_error("IndexIterator::dereference(): can not dereference an invalid iterator");
00124 if(this->m_idx >= this->m_container->size())
00125 throw std::out_of_range("IndexIterator::dereference(): can not increment past the end");
00126 return (*m_container)[m_idx];
00127 }
00128
00129 };
00130
00131 }
00132
00133 }
00134
00135
00136 #endif