00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifndef STLSOFT_INCL_H_STLSOFT
00058 # include <stlsoft.h>
00059 #endif
00060 #ifndef STLSOFT_INCL_RANGELIB_HPP_RANGE_CATEGORIES
00061 # include <rangelib/range_categories.hpp>
00062 #endif
00063 #ifndef STLSOFT_INCL_H_STLSOFT_OPERATOR_BOOL
00064 # include <stlsoft_operator_bool.h>
00065 #endif
00066 #ifndef STLSOFT_INCL_H_STLSOFT_META
00067 # include <stlsoft_meta.h>
00068 #endif
00069 #ifndef STLSOFT_INCL_H_STLSOFT_TYPE_TRAITS
00070 # include <stlsoft_type_traits.h>
00071 #endif
00072 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00073 # include <stlsoft_iterator.h>
00074 #endif
00075
00076 #ifdef STLSOFT_UNITTEST
00077 # include <algorithm>
00078 # include <deque>
00079 # include <list>
00080 # include <numeric>
00081 # include <vector>
00082 #endif
00083
00084
00085
00086
00087
00088 #ifndef _STLSOFT_NO_NAMESPACE
00089 namespace stlsoft
00090 {
00091 #endif
00092
00093
00094
00099
00100
00101
00102
00103
00105 template <ss_typename_param_k I>
00106 struct iterator_range_traits
00107 {
00108 public:
00109 typedef ss_typename_type_k I::value_type value_type;
00110 private:
00111 #ifdef STLSOFT_ITERATOR_ITERATOR_FORM2_SUPPORT
00112
00113 enum { IS_CONST = base_type_traits<value_type>::is_const };
00114 #else
00115
00116 typedef std::iterator_traits<I> traits_type_;
00117
00118 typedef ss_typename_type_k traits_type_::pointer pointer_type_;
00119
00120 enum { IS_CONST = base_type_traits<pointer_type_>::is_const };
00121 #endif
00122
00123 typedef ss_typename_type_k base_type_traits<value_type>::base_type base_value_type;
00124
00125 public:
00127 typedef I iterator;
00129 typedef ss_typename_type_k base_type_traits<iterator>::base_type const &const_iterator;
00131 typedef ss_typename_type_k select_first_type< base_value_type const &
00132 , base_value_type &, IS_CONST>::type reference;
00134 typedef base_value_type const &const_reference;
00135 };
00136
00137 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00138
00139 template <ss_typename_param_k T>
00140 struct iterator_range_traits<T*>
00141 {
00142 typedef T value_type;
00143 typedef value_type *iterator;
00144 typedef value_type const *const_iterator;
00145 typedef value_type &reference;
00146 typedef value_type const &const_reference;
00147 };
00148
00149 template <ss_typename_param_k T>
00150 struct iterator_range_traits<T const*>
00151 {
00152 typedef T value_type;
00153 typedef value_type const *iterator;
00154 typedef value_type const *const_iterator;
00155 typedef value_type const &reference;
00156 typedef value_type const &const_reference;
00157 };
00158
00159 #endif
00160
00183 template< ss_typename_param_k I
00184 , ss_typename_param_k T = iterator_range_traits<I>
00185 >
00186 class iterator_range
00187 : public iterable_range_tag
00188 {
00189 public:
00191 typedef I iterator_type;
00193 typedef T traits_type;
00195 typedef iterable_range_tag range_tag_type;
00197 typedef iterator_range<I, T> class_type;
00199 typedef ss_typename_type_k traits_type::value_type value_type;
00201 typedef ss_typename_type_k traits_type::iterator iterator;
00203 typedef ss_typename_type_k traits_type::const_iterator const_iterator;
00205 typedef ss_typename_type_k traits_type::reference reference;
00207 typedef ss_typename_type_k traits_type::const_reference const_reference;
00208
00209 public:
00211 iterator_range(iterator first, iterator last)
00212 : m_position(first)
00213 , m_last(last)
00214 {}
00215
00217 template <ss_typename_param_k I2>
00218 iterator_range(I2 first, I2 last)
00219 : m_position(first)
00220 , m_last(last)
00221 {}
00222 #ifdef __STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
00223
00224 template <ss_typename_param_k T2, ss_size_t N>
00225 iterator_range(T2 (&ar)[N])
00226 : m_position(&ar[0])
00227 , m_last(&ar[N])
00228 {}
00229 #endif
00230
00233 private:
00234 STLSOFT_DEFINE_OPERATOR_BOOL_TYPES_T(class_type, boolean_generator_type, boolean_type);
00235 public:
00237 ss_bool_t is_open() const
00238 {
00239 return m_position != m_last;
00240 }
00242 reference current()
00243 {
00244 stlsoft_assert(is_open());
00245
00246 return *m_position;
00247 }
00249 const_reference current() const
00250 {
00251 stlsoft_assert(is_open());
00252
00253 return *m_position;
00254 }
00255
00257 operator boolean_type() const
00258 {
00259 return boolean_generator_type::translate(is_open());
00260 }
00262 reference operator *()
00263 {
00264 return current();
00265 }
00267 const_reference operator *() const
00268 {
00269 return current();
00270 }
00271
00273 class_type &advance()
00274 {
00275 stlsoft_message_assert("Attempting to increment the range past its end point", is_open());
00276
00277 ++m_position;
00278
00279 return *this;
00280 }
00282 class_type &operator ++()
00283 {
00284 return advance();
00285 }
00288 class_type operator ++(int)
00289 {
00290 class_type ret(*this);
00291
00292 operator ++();
00293
00294 return ret;
00295 }
00297
00300 public:
00302 iterator begin()
00303 {
00304 return m_position;
00305 }
00307 iterator end()
00308 {
00309 return m_last;
00310 }
00311
00313 const_iterator begin() const
00314 {
00315 return m_position;
00316 }
00318 const_iterator end() const
00319 {
00320 return m_last;
00321 }
00323
00324
00325 private:
00326 iterator m_position;
00327 iterator m_last;
00328 };
00329
00331
00332
00333 #ifdef STLSOFT_UNITTEST
00334
00335 namespace unittest
00336 {
00337 namespace iterator_range_util
00338 {
00339 template <typename T>
00340 ss_bool_t test_container()
00341 {
00342 T cont;
00343 int total0 = 0;
00344 int total1 = 0;
00345
00346 for(int i = 0; i < 100; i += 5)
00347 {
00348 #if defined(__STLSOFT_COMPILER_IS_DMC)
00349 typedef ss_typename_type_k T::value_type value_t;
00350
00351 cont.push_back(value_t(i));
00352 #else
00353 cont.push_back(ss_typename_type_k T::value_type(i));
00354 #endif
00355 }
00356
00357 for(iterator_range<ss_typename_type_k T::iterator> range(cont.begin(), cont.end()); range; ++range)
00358 {
00359 total0 += *range;
00360 }
00361
00362 #if defined(__STLSOFT_COMPILER_IS_DMC)
00363 typedef ss_typename_type_k T::value_type value_t;
00364
00365 total1 = std::accumulate(cont.begin(), cont.end(), value_t(0));
00366 #else
00367 total1 = std::accumulate(cont.begin(), cont.end(), ss_typename_type_k T::value_type(0));
00368 #endif
00369
00370 return total0 == total1;
00371 }
00372 }
00373
00374 ss_bool_t test_rangelib_iterator_range(unittest_reporter *r)
00375 {
00376 using stlsoft::unittest::unittest_initialiser;
00377
00378 ss_bool_t bSuccess = true;
00379
00380 unittest_initialiser init(r, "RangeLib", "iterator_range", __FILE__);
00381
00382 if(!iterator_range_util::test_container<std::list<int> >())
00383 {
00384 r->report("summation over list<int> failed", __LINE__);
00385 bSuccess = false;
00386 }
00387
00388 if(!iterator_range_util::test_container<std::vector<int> >())
00389 {
00390 r->report("summation over vector<int> failed", __LINE__);
00391 bSuccess = false;
00392 }
00393
00394 if(!iterator_range_util::test_container<std::deque<short> >())
00395 {
00396 r->report("summation over deque<short> failed", __LINE__);
00397 bSuccess = false;
00398 }
00399
00400 return bSuccess;
00401 }
00402
00403 unittest_registrar unittest_rangelib_iterator_range(test_rangelib_iterator_range);
00404
00405 }
00406
00407 #endif
00408
00409
00410
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423