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
00070 #ifdef STLSOFT_UNITTEST
00071 # include <algorithm>
00072 # include <deque>
00073 # include <list>
00074 # include <numeric>
00075 # include <vector>
00076 #endif
00077
00078
00079
00080
00081
00082 #ifndef _STLSOFT_NO_NAMESPACE
00083 namespace stlsoft
00084 {
00085 #endif
00086
00087
00088
00093
00094
00095
00096
00097
00098 #ifdef __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00099
00100
00102 template< ss_typename_param_k S
00103 , bool B_CONST
00104 >
00105 struct sequence_range_traits
00106 {
00107 public:
00109 typedef S sequence_type;
00111 typedef S &sequence_reference_type;
00113 typedef ss_typename_type_k sequence_type::value_type value_type;
00115 typedef ss_typename_type_k select_first_type< ss_typename_type_k sequence_type::const_iterator
00116 , ss_typename_type_k sequence_type::iterator
00117 , B_CONST
00118 >::type iterator;
00120 typedef ss_typename_type_k sequence_type::const_iterator const_iterator;
00122 typedef ss_typename_type_k select_first_type< ss_typename_type_k sequence_type::const_reference
00123 , ss_typename_type_k sequence_type::reference
00124 , B_CONST
00125 >::type reference;
00127 typedef ss_typename_type_k sequence_type::const_reference const_reference;
00128
00130
00132
00133 };
00134
00135 template< ss_typename_param_k S
00136 >
00137 struct sequence_range_traits<S, true>
00138 {
00139 public:
00140 typedef S sequence_type;
00141 typedef S &sequence_reference_type;
00142 typedef ss_typename_type_k sequence_type::value_type value_type;
00143 typedef ss_typename_type_k sequence_type::const_iterator iterator;
00144 typedef ss_typename_type_k sequence_type::const_iterator const_iterator;
00145 typedef ss_typename_type_k sequence_type::const_reference reference;
00146 typedef ss_typename_type_k sequence_type::const_reference const_reference;
00147
00148 typedef ss_typename_type_k sequence_type::difference_type difference_type;
00149 typedef ss_typename_type_k sequence_type::size_type size_type;
00150 };
00151 #else
00152 template< ss_typename_param_k S
00153 >
00154 struct sequence_range_traits
00155 {
00156 public:
00157 typedef S sequence_type;
00158 typedef S &sequence_reference_type;
00159 typedef ss_typename_type_k sequence_type::value_type value_type;
00160 typedef ss_typename_type_k sequence_type::iterator iterator;
00161 typedef ss_typename_type_k sequence_type::const_iterator const_iterator;
00162 typedef ss_typename_type_k sequence_type::reference reference;
00163 typedef ss_typename_type_k sequence_type::const_reference const_reference;
00164
00165 typedef ss_typename_type_k sequence_type::difference_type difference_type;
00166 typedef ss_typename_type_k sequence_type::size_type size_type;
00167 };
00168
00169 template< ss_typename_param_k S
00170 >
00171 struct const_sequence_range_traits
00172 {
00173 public:
00174 typedef S sequence_type;
00175 typedef S const &sequence_reference_type;
00176 typedef ss_typename_type_k sequence_type::value_type value_type;
00177 typedef ss_typename_type_k sequence_type::const_iterator iterator;
00178 typedef ss_typename_type_k sequence_type::const_iterator const_iterator;
00179 typedef ss_typename_type_k sequence_type::const_reference reference;
00180 typedef ss_typename_type_k sequence_type::const_reference const_reference;
00181 typedef ss_typename_type_k sequence_type::difference_type difference_type;
00182 typedef ss_typename_type_k sequence_type::size_type size_type;
00183 };
00184 #endif
00185
00207 template< ss_typename_param_k S
00208 #ifdef __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00209 , ss_typename_param_k T = sequence_range_traits<S, is_const<S>::value>
00210 #else
00211 , ss_typename_param_k T = const_sequence_range_traits<S>
00212 #endif
00213 >
00214 class sequence_range
00215 : public iterable_range_tag
00216 {
00217 public:
00219 typedef S sequence_type;
00221 typedef T traits_type;
00223 typedef iterable_range_tag range_tag_type;
00225 typedef sequence_range<S, T> class_type;
00227 typedef ss_typename_type_k traits_type::sequence_reference_type sequence_reference_type;
00229 typedef ss_typename_type_k traits_type::value_type value_type;
00231 typedef ss_typename_type_k traits_type::iterator iterator;
00233 typedef ss_typename_type_k traits_type::const_iterator const_iterator;
00235 typedef ss_typename_type_k traits_type::reference reference;
00237 typedef ss_typename_type_k traits_type::const_reference const_reference;
00239 typedef ss_typename_type_k traits_type::difference_type difference_type;
00241 typedef ss_typename_type_k traits_type::size_type size_type;
00242
00243 public:
00244 sequence_range(sequence_reference_type seq)
00245 : m_position(seq.begin())
00246 , m_last(seq.end())
00247 {}
00248 template <ss_typename_param_k I>
00249 sequence_range(I first, I last)
00250 : m_position(first)
00251 , m_last(last)
00252 {}
00253 #ifdef __STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
00254
00255
00256 template <ss_size_t N>
00257 sequence_range(S (&ar)[N])
00258 : m_position(&ar[0])
00259 , m_last(&ar[N])
00260 {}
00261 #endif
00262
00265 private:
00266 STLSOFT_DEFINE_OPERATOR_BOOL_TYPES_T(class_type, boolean_generator_type, boolean_type);
00267 public:
00269 ss_bool_t is_open() const
00270 {
00271 return m_position != m_last;
00272 }
00274 reference current()
00275 {
00276 stlsoft_assert(is_open());
00277
00278
00279
00280 return *m_position;
00281 }
00283 const_reference current() const
00284 {
00285 stlsoft_assert(is_open());
00286
00287 return *m_position;
00288 }
00290 class_type &advance()
00291 {
00292 stlsoft_message_assert("Attempting to increment the range past its end point", is_open());
00293
00294 ++m_position;
00295
00296 return *this;
00297 }
00298
00300 operator boolean_type() const
00301 {
00302 return boolean_generator_type::translate(is_open());
00303 }
00305 reference operator *()
00306 {
00307 return current();
00308 }
00310 const_reference operator *() const
00311 {
00312 return current();
00313 }
00315 class_type &operator ++()
00316 {
00317 return advance();
00318 }
00321 class_type operator ++(int)
00322 {
00323 class_type ret(*this);
00324
00325 operator ++();
00326
00327 return ret;
00328 }
00330
00333 public:
00335 iterator begin()
00336 {
00337 return m_position;
00338 }
00340 iterator end()
00341 {
00342 return m_last;
00343 }
00344
00346 const_iterator begin() const
00347 {
00348 return m_position;
00349 }
00351 const_iterator end() const
00352 {
00353 return m_last;
00354 }
00356
00357
00358 private:
00359 iterator m_position;
00360 iterator m_last;
00361 value_type m_value;
00362 };
00363
00365
00366
00367 #ifdef STLSOFT_UNITTEST
00368
00369 namespace unittest
00370 {
00371 namespace sequence_range_util
00372 {
00373 template <typename T>
00374 ss_bool_t test_container()
00375 {
00376 T cont;
00377 int total0 = 0;
00378 int total1 = 0;
00379
00380 for(int i = 0; i < 100; i += 5)
00381 {
00382 #if defined(__STLSOFT_COMPILER_IS_DMC)
00383 typedef ss_typename_type_k T::value_type value_t;
00384
00385 cont.push_back(value_t(i));
00386 #else
00387 cont.push_back(ss_typename_type_k T::value_type(i));
00388 #endif
00389 }
00390
00391 for(sequence_range<T> range(cont.begin(), cont.end()); range; ++range)
00392 {
00393 total0 += *range;
00394 }
00395
00396 #if defined(__STLSOFT_COMPILER_IS_DMC)
00397 typedef ss_typename_type_k T::value_type value_t;
00398
00399 total1 = std::accumulate(cont.begin(), cont.end(), value_t(0));
00400 #else
00401 total1 = std::accumulate(cont.begin(), cont.end(), ss_typename_type_k T::value_type(0));
00402 #endif
00403
00404 return total0 == total1;
00405 }
00406 }
00407
00408 ss_bool_t test_rangelib_sequence_range(unittest_reporter *r)
00409 {
00410 using stlsoft::unittest::unittest_initialiser;
00411
00412 ss_bool_t bSuccess = true;
00413
00414 unittest_initialiser init(r, "RangeLib", "sequence_range", __FILE__);
00415
00416 if(!sequence_range_util::test_container<std::list<int> >())
00417 {
00418 r->report("summation over list<int> failed", __LINE__);
00419 bSuccess = false;
00420 }
00421
00422 if(!sequence_range_util::test_container<std::vector<int> >())
00423 {
00424 r->report("summation over vector<int> failed", __LINE__);
00425 bSuccess = false;
00426 }
00427
00428 if(!sequence_range_util::test_container<std::deque<short> >())
00429 {
00430 r->report("summation over deque<short> failed", __LINE__);
00431 bSuccess = false;
00432 }
00433
00434 return bSuccess;
00435 }
00436
00437 unittest_registrar unittest_rangelib_sequence_range(test_rangelib_sequence_range);
00438
00439 }
00440
00441 #endif
00442
00443
00444
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457