STLSoft - ... Robust, Lightweight, Cross-platform, Template Software ... ATLSTL - Template Software for the Active Template Library COMSTL - The Standard Template Library meets the Component Object Model .netSTL - Standard Template Library meets the Microsoft.NET Common Language Runtime InetSTL - The Standard Template Library meets WinInet MFCSTL - Template Software for the Microsoft Foundation Classes UNIXSTL - Template Software for the UNIX Operating System WinSTL - where the Standard Template Library meets the Win32 API

Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

iterator_range.hpp

Go to the documentation of this file.
00001 /* 
00002  * File:        rangelib/iterator_range.hpp
00003  *
00004  * Purpose:     Iterator range adaptor.
00005  *
00006  * Created:     4th November 2003
00007  * Updated:     12th September 2004
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 2003-2004, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer.
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * 
00039 
00040 
00043 #ifndef STLSOFT_INCL_RANGELIB_HPP_ITERATOR_RANGE
00044 #define STLSOFT_INCL_RANGELIB_HPP_ITERATOR_RANGE
00045 
00046 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00047 # define STLSOFT_VER_RANGELIB_HPP_ITERATOR_RANGE_MAJOR    1
00048 # define STLSOFT_VER_RANGELIB_HPP_ITERATOR_RANGE_MINOR    0
00049 # define STLSOFT_VER_RANGELIB_HPP_ITERATOR_RANGE_REVISION 7
00050 # define STLSOFT_VER_RANGELIB_HPP_ITERATOR_RANGE_EDIT     10
00051 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00052 
00053 /* 
00054  * Includes
00055  */
00056 
00057 #ifndef STLSOFT_INCL_H_STLSOFT
00058 # include <stlsoft.h>                           // Include the STLSoft root header
00059 #endif /* !STLSOFT_INCL_H_STLSOFT */
00060 #ifndef STLSOFT_INCL_RANGELIB_HPP_RANGE_CATEGORIES
00061 # include <rangelib/range_categories.hpp>
00062 #endif /* !STLSOFT_INCL_RANGELIB_HPP_RANGE_CATEGORIES */
00063 #ifndef STLSOFT_INCL_H_STLSOFT_OPERATOR_BOOL
00064 # include <stlsoft_operator_bool.h> //
00065 #endif /* !STLSOFT_INCL_H_STLSOFT_OPERATOR_BOOL */
00066 #ifndef STLSOFT_INCL_H_STLSOFT_META
00067 # include <stlsoft_meta.h>  //
00068 #endif /* !STLSOFT_INCL_H_STLSOFT_META */
00069 #ifndef STLSOFT_INCL_H_STLSOFT_TYPE_TRAITS
00070 # include <stlsoft_type_traits.h>   //
00071 #endif /* !STLSOFT_INCL_H_STLSOFT_TYPE_TRAITS */
00072 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00073 # include <stlsoft_iterator.h>   //
00074 #endif /* !STLSOFT_INCL_H_STLSOFT_ITERATOR */
00075 
00076 #ifdef STLSOFT_UNITTEST
00077 # include <algorithm>
00078 # include <deque>
00079 # include <list>
00080 # include <numeric>
00081 # include <vector>
00082 #endif /* STLSOFT_UNITTEST */
00083 
00084 /* 
00085  * Namespace
00086  */
00087 
00088 #ifndef _STLSOFT_NO_NAMESPACE
00089 namespace stlsoft
00090 {
00091 #endif /* _STLSOFT_NO_NAMESPACE */
00092 
00093 /* 
00094 
00099 
00100 /* 
00101  * Classes
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     // Use the iterator itself to determine whether the iterator is const
00113     enum { IS_CONST = base_type_traits<value_type>::is_const };
00114 #else /* ? STLSOFT_ITERATOR_ITERATOR_FORM2_SUPPORT */
00115     // 1. Use iterator_traits ...
00116     typedef std::iterator_traits<I>                                                     traits_type_;
00117     // ... to get the pointer type ...
00118     typedef ss_typename_type_k traits_type_::pointer                                    pointer_type_;
00119     // ... to determine whether the iterator is const
00120     enum { IS_CONST = base_type_traits<pointer_type_>::is_const };
00121 #endif /* !STLSOFT_ITERATOR_ITERATOR_FORM2_SUPPORT */
00122     // 2. Use Determine the base type of the value_type, which may then be used to create a reference of the appropriate type
00123     typedef ss_typename_type_k base_type_traits<value_type>::base_type                  base_value_type;
00124 //  enum { IS_CONST = is_const<pointer>::value };
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 /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
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 /* __STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
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 // Members
00325 private:
00326     iterator  m_position;
00327     iterator  m_last;
00328 };
00329 
00331 // Unit-testing
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 /* ? compiler */
00353                 cont.push_back(ss_typename_type_k T::value_type(i));
00354 #endif /* compiler */
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 /* ? compiler */
00367             total1 = std::accumulate(cont.begin(), cont.end(), ss_typename_type_k T::value_type(0));
00368 #endif /* compiler */
00369 
00370             return total0 == total1;
00371         }
00372     } // namespace iterator_range_util
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 } // namespace unittest
00406 
00407 #endif /* STLSOFT_UNITTEST */
00408 
00409 /* 
00410 
00412 
00413 /* 
00414 
00415 #ifndef _STLSOFT_NO_NAMESPACE
00416 } // namespace stlsoft
00417 #endif /* _STLSOFT_NO_NAMESPACE */
00418 
00419 /* 
00420 
00421 #endif /* !STLSOFT_INCL_RANGELIB_HPP_ITERATOR_RANGE */
00422 
00423 /* 

STLSoft Libraries documentation © Synesis Software Pty Ltd, 2001-2004