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  

sequence_range.hpp

Go to the documentation of this file.
00001 /* 
00002  * File:        rangelib/sequence_range.hpp
00003  *
00004  * Purpose:     Sequence container 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_SEQUENCE_RANGE
00044 #define STLSOFT_INCL_RANGELIB_HPP_SEQUENCE_RANGE
00045 
00046 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00047 # define STLSOFT_VER_RANGELIB_HPP_SEQUENCE_RANGE_MAJOR    1
00048 # define STLSOFT_VER_RANGELIB_HPP_SEQUENCE_RANGE_MINOR    3
00049 # define STLSOFT_VER_RANGELIB_HPP_SEQUENCE_RANGE_REVISION 2
00050 # define STLSOFT_VER_RANGELIB_HPP_SEQUENCE_RANGE_EDIT     15
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 
00070 #ifdef STLSOFT_UNITTEST
00071 # include <algorithm>
00072 # include <deque>
00073 # include <list>
00074 # include <numeric>
00075 # include <vector>
00076 #endif /* STLSOFT_UNITTEST */
00077 
00078 /* 
00079  * Namespace
00080  */
00081 
00082 #ifndef _STLSOFT_NO_NAMESPACE
00083 namespace stlsoft
00084 {
00085 #endif /* _STLSOFT_NO_NAMESPACE */
00086 
00087 /* 
00088 
00093 
00094 /* 
00095  * Classes
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 // TODO: Stick in the member-finder stuff here, so can assume ptrdiff_t if none found
00130     typedef ss_typename_type_k sequence_type::difference_type       difference_type;
00132     typedef ss_typename_type_k sequence_type::size_type             size_type;
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 // TODO: Stick in the member-finder stuff here, so can assume ptrdiff_t if none found
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 /* ? __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
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 // TODO: Stick in the member-finder stuff here, so can assume ptrdiff_t if none found
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 /* __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
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>    // Determines whether the sequence is const
00210 #else /* ? __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
00211         ,   ss_typename_param_k T = const_sequence_range_traits<S>                  // Determines whether the sequence is const
00212 #endif /* __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
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) // The constness of this will require some thinking about. Maybe need sequence_range and const_sequence_range??
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 //  template <ss_typename_param_k T2, ss_size_t N>
00255 //    sequence_range(T2 (&ar)[N])
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 /* __STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
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 //      m_value = *m_position;
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 // Members
00358 private:
00359     iterator    m_position;
00360     iterator    m_last;
00361     value_type  m_value;
00362 };
00363 
00365 // Unit-testing
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 /* ? compiler */
00387                 cont.push_back(ss_typename_type_k T::value_type(i));
00388 #endif /* compiler */
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 /* ? compiler */
00401             total1 = std::accumulate(cont.begin(), cont.end(), ss_typename_type_k T::value_type(0));
00402 #endif /* compiler */
00403 
00404             return total0 == total1;
00405         }
00406     } // namespace sequence_range_util
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 } // namespace unittest
00440 
00441 #endif /* STLSOFT_UNITTEST */
00442 
00443 /* 
00444 
00446 
00447 /* 
00448 
00449 #ifndef _STLSOFT_NO_NAMESPACE
00450 } // namespace stlsoft
00451 #endif /* _STLSOFT_NO_NAMESPACE */
00452 
00453 /* 
00454 
00455 #endif /* !STLSOFT_INCL_RANGELIB_HPP_SEQUENCE_RANGE */
00456 
00457 /* 

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