Silicium
iterator_range.hpp
Go to the documentation of this file.
1 #ifndef SILICIUM_ITERATOR_RANGE_HPP
2 #define SILICIUM_ITERATOR_RANGE_HPP
3 
4 #include <silicium/config.hpp>
5 #include <silicium/is_handle.hpp>
6 #include <boost/static_assert.hpp>
7 #include <boost/range/begin.hpp>
8 #include <boost/range/end.hpp>
9 #include <boost/utility/addressof.hpp>
10 #include <cassert>
11 
12 namespace Si
13 {
14  namespace detail
15  {
16  //std::iterator_traits<T const *>::value_type seems to be T (GCC 4.8), but that
17  //is not useful at all because the const is missing.
18  template <class Iterator>
20  {
21  typedef typename std::remove_reference<decltype(*std::declval<Iterator>())>::type type;
22  };
23  }
24 
25  template <class Iterator>
27  {
28  typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
30  typedef Iterator iterator;
31  typedef Iterator const_iterator;
32 
33  BOOST_CONSTEXPR iterator_range() BOOST_NOEXCEPT
34  : m_begin(Iterator())
35  , m_end(Iterator())
36  {
37  }
38 
39  template <class It1, class It2>
40  BOOST_CONSTEXPR iterator_range(It1 &&begin, It2 &&end) BOOST_NOEXCEPT
41  : m_begin(std::forward<It1>(begin))
42  , m_end(std::forward<It2>(end))
43  {
44  }
45 
46  template <class OtherIterator>
47  iterator_range(iterator_range<OtherIterator> const &other) BOOST_NOEXCEPT
48  : m_begin(other.begin())
49  , m_end(other.end())
50  {
51  }
52 
53  template <class OtherIterator>
55  {
56  m_begin = other.begin();
57  m_end = other.end();
58  return *this;
59  }
60 
61  BOOST_CONSTEXPR Iterator const &begin() const BOOST_NOEXCEPT
62  {
63  return m_begin;
64  }
65 
66  BOOST_CONSTEXPR Iterator const &end() const BOOST_NOEXCEPT
67  {
68  return m_end;
69  }
70 
71  BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT
72  {
73  return m_begin == m_end;
74  }
75 
78  BOOST_CONSTEXPR difference_type size() const BOOST_NOEXCEPT
79  {
80  return m_end - m_begin;
81  }
82 
85  SILICIUM_CXX14_CONSTEXPR void pop_front(difference_type n) BOOST_NOEXCEPT
86  {
87  assert(n <= size());
88  m_begin += n;
89  }
90 
91  SILICIUM_CXX14_CONSTEXPR void pop_front() BOOST_NOEXCEPT
92  {
93  assert(!empty());
94  ++m_begin;
95  }
96 
97  value_type &front() const BOOST_NOEXCEPT
98  {
99  assert(!empty());
100  return *begin();
101  }
102 
104  value_type &operator[](difference_type index) const BOOST_NOEXCEPT
105  {
106  static_cast<std::random_access_iterator_tag>(typename std::iterator_traits<Iterator>::iterator_category{});
107  assert(index < size());
108  return begin()[index];
109  }
110 
111  private:
112 
113  Iterator m_begin, m_end;
114  };
115 
116  template <class Iterator1, class Iterator2>
117  BOOST_CONSTEXPR bool pointing_to_same_subrange(iterator_range<Iterator1> const &left, iterator_range<Iterator2> const &right)
118  {
119  return (left.begin() == right.begin()) && (left.end() == right.end());
120  }
121 
122  template <class Iterator>
123  BOOST_CONSTEXPR Iterator const &begin(iterator_range<Iterator> const &range)
124  {
125  return range.begin();
126  }
127 
128  //for Boost.Range compatibility
129  template <class Iterator>
130  BOOST_CONSTEXPR Iterator const &range_begin(iterator_range<Iterator> const &range)
131  {
132  return range.begin();
133  }
134 
135  template <class Iterator>
136  BOOST_CONSTEXPR Iterator const &end(iterator_range<Iterator> const &range)
137  {
138  return range.end();
139  }
140 
141  template <class Iterator1, class Iterator2>
142  BOOST_CONSTEXPR auto make_iterator_range(Iterator1 &&begin, Iterator2 &&end)
143 #if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
145 #endif
146  {
147  typedef typename std::decay<Iterator1>::type iterator_type;
148  BOOST_STATIC_ASSERT((std::is_same<iterator_type, typename std::decay<Iterator2>::type>::value));
149  return iterator_range<iterator_type>(std::forward<Iterator1>(begin), std::forward<Iterator2>(end));
150  }
151 
152  template <class Range>
153  auto make_iterator_range(Range &&range)
154 #if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
155  -> decltype(make_iterator_range(std::begin(range), std::end(range)))
156 #endif
157  {
158  using std::begin;
159  using std::end;
160  return make_iterator_range(begin(range), end(range));
161  }
162 
163  template <class ContiguousRange>
164  auto make_contiguous_range(ContiguousRange &&range)
165 #if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
166  -> decltype(make_iterator_range(boost::addressof(*std::begin(range)), boost::addressof(*std::end(range))))
167 #endif
168  {
169  using std::begin;
170  using std::end;
171  auto begin_ = begin(range);
172  auto end_ = end(range);
173  if (begin_ == end_)
174  {
175  typename std::remove_reference<decltype(*begin_)>::type *data = nullptr;
176  return make_iterator_range(data, data);
177  }
178  auto * const data_begin = boost::addressof(*begin_);
179  auto * const data_end = data_begin + std::distance(begin_, end_);
180  return make_iterator_range(data_begin, data_end);
181  }
182 }
183 
184 #endif
value_type & front() const BOOST_NOEXCEPT
Definition: iterator_range.hpp:97
Definition: iterator_range.hpp:19
BOOST_STATIC_ASSERT(Si::is_handle< absolute_path >::value)
BOOST_CONSTEXPR Iterator const & range_begin(iterator_range< Iterator > const &range)
Definition: iterator_range.hpp:130
BOOST_CONSTEXPR Iterator const & begin() const BOOST_NOEXCEPT
Definition: iterator_range.hpp:61
Definition: absolute_path.hpp:352
BOOST_CONSTEXPR bool pointing_to_same_subrange(iterator_range< Iterator1 > const &left, iterator_range< Iterator2 > const &right)
Definition: iterator_range.hpp:117
SILICIUM_CXX14_CONSTEXPR void pop_front(difference_type n) BOOST_NOEXCEPT
Definition: iterator_range.hpp:85
Definition: absolute_path.hpp:19
value_type & operator[](difference_type index) const BOOST_NOEXCEPT
This method is only available with random access iterators so that it takes O(1) in time...
Definition: iterator_range.hpp:104
BOOST_CONSTEXPR iterator_range() BOOST_NOEXCEPT
Definition: iterator_range.hpp:33
BOOST_CONSTEXPR Iterator const & end(iterator_range< Iterator > const &range)
Definition: iterator_range.hpp:136
iterator_range(iterator_range< OtherIterator > const &other) BOOST_NOEXCEPT
Definition: iterator_range.hpp:47
Iterator const_iterator
Definition: iterator_range.hpp:31
std::iterator_traits< Iterator >::difference_type difference_type
Definition: iterator_range.hpp:28
detail::actual_value_type< Iterator >::type value_type
Definition: iterator_range.hpp:29
SILICIUM_CXX14_CONSTEXPR void pop_front() BOOST_NOEXCEPT
Definition: iterator_range.hpp:91
BOOST_CONSTEXPR Iterator const & begin(iterator_range< Iterator > const &range)
Definition: iterator_range.hpp:123
Definition: iterator_range.hpp:26
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT
Definition: iterator_range.hpp:71
BOOST_CONSTEXPR auto make_iterator_range(Iterator1 &&begin, Iterator2 &&end) -> iterator_range< typename std::decay< Iterator1 >::type >
Definition: iterator_range.hpp:142
BOOST_CONSTEXPR iterator_range(It1 &&begin, It2 &&end) BOOST_NOEXCEPT
Definition: iterator_range.hpp:40
BOOST_CONSTEXPR Iterator const & end() const BOOST_NOEXCEPT
Definition: iterator_range.hpp:66
Iterator iterator
Definition: iterator_range.hpp:30
iterator_range & operator=(iterator_range< OtherIterator > const &other) BOOST_NOEXCEPT
Definition: iterator_range.hpp:54
std::remove_reference< decltype(*std::declval< Iterator >))>::type type
Definition: iterator_range.hpp:21
auto make_contiguous_range(ContiguousRange &&range) -> decltype(make_iterator_range(boost::addressof(*std::begin(range)), boost::addressof(*std::end(range))))
Definition: iterator_range.hpp:164
#define SILICIUM_CXX14_CONSTEXPR
Definition: config.hpp:151
BOOST_CONSTEXPR difference_type size() const BOOST_NOEXCEPT
Definition: iterator_range.hpp:78