00001 /* 00002 Copyright (C) 2010 - 2014, 2019 Christoph Hänisch 00003 00004 Chair of Medical Engineering (mediTEC) 00005 RWTH Aachen University 00006 Pauwelsstr. 20 00007 52074 Aachen 00008 Germany 00009 00010 See license.txt for more information. 00011 00012 Version 0.1.2 (2019-05-21) 00013 */ 00014 00020 #ifndef RANGE_HPP_7631082974 00021 #define RANGE_HPP_7631082974 00022 00023 00024 #include "Iterator.hpp" 00025 00026 00027 namespace TRTK 00028 { 00029 00030 00032 // Range // 00034 00035 00089 template <class T> 00090 class Range 00091 { 00092 private: 00093 00094 typedef void (Range<T>::*bool_type)() const; 00095 void safe_bool_idiom_helper_function() const; 00096 00097 public: 00098 00099 Range(); 00100 Range(const Iterator<T> & begin, const Iterator<T> & end); 00101 Range(const Range<T> & other); 00102 virtual ~Range(); 00103 00104 Range<T> & operator=(const Range<T> & other); 00105 bool operator==(const Range<T> & other) const; 00106 bool operator!=(const Range<T> & other) const; 00107 operator bool_type() const; // safe bool idiom 00108 00109 Iterator<T> begin() const; 00110 Iterator<T> end() const; 00111 00112 bool isValid() const; 00113 bool isEmpty() const; 00114 00115 void first() const; 00116 bool isDone() const; 00117 void next() const; 00118 T currentItem() const; 00119 00120 size_t size() const; 00121 00122 typedef Iterator<T> const_iterator; 00123 00124 private: 00125 00126 Iterator<T> m_begin; 00127 Iterator<T> m_end; 00128 mutable Iterator<T> m_current; 00129 }; 00130 00131 00134 template <class T> 00135 Range<T>::Range() 00136 { 00137 } 00138 00139 00142 template <class T> 00143 Range<T>::Range(const Range<T> & other) : m_begin(other.m_begin), m_end(other.m_end), m_current(other.m_begin) 00144 { 00145 } 00146 00147 00156 template <class T> 00157 Range<T>::Range(const Iterator<T> & begin, const Iterator<T> & end) : m_begin(begin), m_end(end), m_current(begin) 00158 { 00159 } 00160 00161 00164 template <class T> 00165 Range<T>::~Range() 00166 { 00167 } 00168 00169 00172 template <class T> 00173 Range<T> & Range<T>::operator=(const Range<T> & other) 00174 { 00175 if (this == &other) return *this; 00176 00177 m_begin = other.m_begin; 00178 m_end = other.m_end; 00179 m_current = other.m_begin; 00180 00181 return *this; 00182 } 00183 00184 00206 template <class T> 00207 bool Range<T>::operator==(const Range<T> & other) const 00208 { 00209 if (isValid() && other.isValid()) 00210 { 00211 return (m_begin == other.m_begin) && (m_end == other.m_end); 00212 } 00213 else if (!m_begin.isValid() && !other.begin().isValid() && !m_end.isValid() && !other.end().isValid()) 00214 { 00215 return true; 00216 } 00217 else 00218 { 00219 return false; 00220 } 00221 } 00222 00223 00226 template <class T> 00227 bool Range<T>::operator!=(const Range<T> & other) const 00228 { 00229 return !(*this == other); 00230 } 00231 00232 00244 template <class T> 00245 Range<T>::operator typename Range<T>::bool_type() const // safe bool idiom 00246 { 00247 return isValid() ? &Range<T>::safe_bool_idiom_helper_function : NULL; 00248 } 00249 00250 00251 template <class T> 00252 void Range<T>::safe_bool_idiom_helper_function() const 00253 { 00254 } 00255 00256 00259 template <class T> 00260 Iterator<T> Range<T>::begin() const 00261 { 00262 return m_begin; 00263 } 00264 00265 00268 template <class T> 00269 T Range<T>::currentItem() const 00270 { 00271 if (m_begin && m_end) 00272 { 00273 if (m_current != m_end) 00274 { 00275 return *m_current; 00276 } 00277 else 00278 { 00279 throw std::range_error("Range<T>::next(): The last element was already reached."); 00280 } 00281 } 00282 else 00283 { 00284 throw std::range_error("Range<T>::next(): This instance does not reference any iterators."); 00285 } 00286 } 00287 00288 00291 template <class T> 00292 Iterator<T> Range<T>::end() const 00293 { 00294 return m_end; 00295 } 00296 00297 00300 template <class T> 00301 void Range<T>::first() const 00302 { 00303 m_current = m_begin; 00304 } 00305 00306 00309 template <class T> 00310 bool Range<T>::isDone() const 00311 { 00312 if (m_begin && m_end) 00313 { 00314 return m_current == m_end; 00315 } 00316 else 00317 { 00318 return true; 00319 } 00320 } 00321 00322 00328 template <class T> 00329 bool Range<T>::isEmpty() const 00330 { 00331 if (m_begin && m_end) 00332 { 00333 return m_begin == m_end; 00334 } 00335 else 00336 { 00337 return true; 00338 } 00339 } 00340 00341 00361 template <class T> 00362 bool Range<T>::isValid() const 00363 { 00364 return m_begin.isValid() && m_end.isValid(); 00365 } 00366 00367 00370 template <class T> 00371 void Range<T>::next() const 00372 { 00373 if (m_begin && m_end) 00374 { 00375 if (m_current != m_end) 00376 { 00377 ++m_current; 00378 } 00379 else 00380 { 00381 throw std::range_error("Range<T>::next(): The last element was already reached."); 00382 } 00383 } 00384 else 00385 { 00386 throw std::range_error("Range<T>::next(): This instance does not reference any iterators."); 00387 } 00388 } 00389 00390 00396 template <class T> 00397 size_t Range<T>::size() const 00398 { 00399 if (m_begin && m_end) 00400 { 00401 return distance(m_begin, m_end); 00402 } 00403 else 00404 { 00405 return 0; 00406 } 00407 } 00408 00409 00423 template <class Sequence> 00424 Range<typename Sequence::value_type> make_range(const Sequence & sequence) 00425 { 00426 typedef typename Sequence::value_type T; // TODO: in C++11 second template parameter class T = Sequence::value_type 00427 const Iterator<T> & begin = IteratorAdapter<T, typename Sequence::const_iterator>(sequence.begin()); 00428 const Iterator<T> & end = IteratorAdapter<T, typename Sequence::const_iterator>(sequence.end()); 00429 return Range<T>(begin, end); 00430 } 00431 00432 00433 } // namespace TRTK 00434 00435 00436 #endif // RANGE_HPP_7631082974
Documentation generated by Doxygen