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  

stlsoft_auto_buffer.h

Go to the documentation of this file.
00001 /* 
00002  * File:        stlsoft_auto_buffer.h (originally MTLocBfr.h, ::SynesisStl)
00003  *
00004  * Purpose:     Contains the auto_buffer template class.
00005  *
00006  * Created:     19th January 2002
00007  * Updated:     11th September 2004
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 2002-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 
00044 
00045 #ifndef STLSOFT_INCL_H_STLSOFT_AUTO_BUFFER
00046 #define STLSOFT_INCL_H_STLSOFT_AUTO_BUFFER
00047 
00048 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00049 # define STLSOFT_VER_H_STLSOFT_AUTO_BUFFER_MAJOR     2
00050 # define STLSOFT_VER_H_STLSOFT_AUTO_BUFFER_MINOR     0
00051 # define STLSOFT_VER_H_STLSOFT_AUTO_BUFFER_REVISION  1
00052 # define STLSOFT_VER_H_STLSOFT_AUTO_BUFFER_EDIT      86
00053 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00054 
00055 /* 
00056  * Includes
00057  */
00058 
00059 #ifndef STLSOFT_INCL_H_STLSOFT
00060 # include "stlsoft.h"                   // Include the STLSoft root header
00061 #endif /* !STLSOFT_INCL_H_STLSOFT */
00062 #ifdef _STLSOFT_AUTO_BUFFER_ALLOW_UDT
00063 # define _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
00064 # ifdef _STLSOFT_COMPILE_VERBOSE
00065 #  pragma message("_STLSOFT_AUTO_BUFFER_ALLOW_UDT is deprecated. Use _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD instead")
00066 # endif /* _STLSOFT_COMPILE_VERBOSE */
00067 #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_UDT */
00068 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00069 # ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00070 #  include "stlsoft_iterator.h"         // reverse_iterator_base
00071 # endif /* !STLSOFT_INCL_H_STLSOFT_ITERATOR */
00072 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00073 #ifndef _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
00074 # ifndef STLSOFT_INCL_H_CONSTRAINTS
00075 #  include "stlsoft_constraints.h"      // Include the STLSoft constraints header
00076 # endif /* !STLSOFT_INCL_H_CONSTRAINTS */
00077 #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD */
00078 #ifndef STLSOFT_INCL_H_STLSOFT_SIMPLE_ALGORITHMS
00079 # include "stlsoft_simple_algorithms.h" //
00080 #endif /* !STLSOFT_INCL_H_STLSOFT_SIMPLE_ALGORITHMS */
00081 #ifdef STLSOFT_UNITTEST
00082 # ifndef STLSOFT_INCL_H_STLSOFT_NEW_ALLOCATOR
00083 #  include "stlsoft_new_allocator.h"    // new_allocator
00084 # endif /* !STLSOFT_INCL_H_STLSOFT_NEW_ALLOCATOR */
00085 # include <numeric>                     // accumulate
00086 #endif /* STLSOFT_UNITTEST */
00087 
00088 /* 
00089  * Namespace
00090  */
00091 
00092 #ifndef _STLSOFT_NO_NAMESPACE
00093 namespace stlsoft
00094 {
00095 #endif /* _STLSOFT_NO_NAMESPACE */
00096 
00097 /* 
00098  * Classes
00099  */
00100 
00101 // class auto_buffer
00102 //
00118 
00119 template<   ss_typename_param_k T
00120         ,   ss_typename_param_k A
00121 #ifdef __STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT
00122 # if !defined(__STLSOFT_COMPILER_IS_BORLAND) || \
00123      __BORLANDC__ < 0x0551
00124         ,   ss_size_t           SPACE = 256
00125 # else /* ? compiler */
00126         ,   ss_size_t           space = 256
00127 # endif /* compiler */
00128 #else
00129 # if !defined(__STLSOFT_COMPILER_IS_BORLAND) || \
00130      __BORLANDC__ < 0x0551
00131         ,   ss_size_t           SPACE /* = 256 */
00132 # else /* ? compiler */
00133         ,   ss_size_t           space /* = 256 */
00134 # endif /* compiler */
00135 #endif /* __STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
00136         >
00137 class auto_buffer
00138 #if !defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE)
00139     : protected A
00140 #endif /* !STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
00141 {
00143 
00144 public:
00146     typedef T                       value_type;
00148     typedef A                       allocator_type;
00149 #if !defined(__STLSOFT_COMPILER_IS_BORLAND) || \
00150     __BORLANDC__ < 0x0551
00151     enum
00152     {
00154         space = SPACE
00155     };
00156 #endif /* compiler */
00157 
00158     typedef auto_buffer<T, A, space>                            class_type;
00160     typedef ss_typename_type_k allocator_type::reference        reference;
00162     typedef ss_typename_type_k allocator_type::const_reference  const_reference;
00164     typedef ss_typename_type_k allocator_type::pointer          pointer;
00166     typedef ss_typename_type_k allocator_type::const_pointer    const_pointer;
00168     typedef ss_size_t                                           size_type;
00170     typedef ss_ptrdiff_t                                        difference_type;
00171 #if !defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00172 
00173     typedef value_type                                          *iterator;
00175     typedef value_type const                                    *const_iterator;
00176 #else /* ? !__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00177 
00178     typedef
00179 # if !defined(__STLSOFT_COMPILER_IS_BORLAND)
00180            ss_typename_type_k
00181 # endif /* compiler */
00182                        pointer_iterator <   value_type
00183                                         ,   pointer
00184                                         ,   reference
00185                                         >::iterator_type    iterator;
00187     typedef
00188 # if !defined(__STLSOFT_COMPILER_IS_BORLAND)
00189          ss_typename_type_k
00190 # endif /* __STLSOFT_COMPILER_IS_BORLAND */
00191                        pointer_iterator <   value_type const
00192                                         ,   const_pointer
00193                                         ,   const_reference
00194                                         >::iterator_type    const_iterator;
00195 
00197     typedef reverse_iterator_base       <   iterator
00198                                         ,   value_type
00199                                         ,   reference
00200                                         ,   pointer
00201                                         ,   difference_type
00202                                         >                   reverse_iterator;
00203 
00205     typedef const_reverse_iterator_base <   const_iterator
00206                                         ,   value_type const
00207                                         ,   const_reference
00208                                         ,   const_pointer
00209                                         ,   difference_type
00210                                         >                   const_reverse_iterator;
00211 #endif /* !__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00212 
00213 
00215 
00216 private:
00217     pointer allocate_(size_type cItems, void *hint)
00218     {
00219 #ifdef __STLSOFT_CF_ALLOCATOR_ALLOCATE_HAS_HINT
00220         return get_allocator().allocate(cItems, hint);
00221 #else
00222         STLSOFT_SUPPRESS_UNUSED(hint);
00223 
00224         return get_allocator().allocate(cItems);
00225 #endif /* __STLSOFT_CF_ALLOCATOR_ALLOCATE_HAS_HINT */
00226     }
00227 
00228     pointer allocate_(size_type cItems)
00229     {
00230 #ifdef __STLSOFT_CF_ALLOCATOR_ALLOCATE_HAS_HINT
00231         return get_allocator().allocate(cItems, NULL);
00232 #else
00233         return get_allocator().allocate(cItems);
00234 #endif /* __STLSOFT_CF_ALLOCATOR_ALLOCATE_HAS_HINT */
00235     }
00236 
00237     void deallocate_(pointer p, size_type cItems)
00238     {
00239         stlsoft_assert(NULL != p);
00240 
00241 #ifdef __STLSOFT_CF_ALLOCATOR_DEALLOCATE_HAS_OBJECTCOUNT
00242         get_allocator().deallocate(p, cItems);
00243 #else
00244         STLSOFT_SUPPRESS_UNUSED(cItems);
00245 
00246         get_allocator().deallocate(p);
00247 #endif /* __STLSOFT_CF_ALLOCATOR_DEALLOCATE_HAS_OBJECTCOUNT */
00248     }
00249 
00250     pointer reallocate_(pointer p, size_type cItems, size_type cNewItems)
00251     {
00252         pointer new_p   =   allocate_(cNewItems, p);
00253 
00254         // This test is needed, since some allocators may not throw
00255         // bad_alloc
00256         if(NULL != new_p)
00257         {
00258             block_copy(new_p, p, cItems);
00259 
00260             deallocate_(p, cItems);
00261         }
00262 
00263         return new_p;
00264     }
00265 protected:
00266     static void block_copy(pointer dest, const_pointer src, size_type cItems)
00267     {
00268         pod_copy_n(dest, src, cItems);
00269     }
00270     static void block_set(pointer dest, size_type cItems, const_reference value)
00271     {
00272         pod_fill_n(dest, cItems, value);
00273     }
00275 
00277 
00278 public:
00289     ss_explicit_k auto_buffer(size_type cItems)
00290         : m_buffer((space < cItems) ? allocate_(cItems) : const_cast<pointer>(&m_internal[0]))
00291         , m_cItems((NULL != m_buffer) ? cItems : 0)
00292     {
00293         // Can't create one with an empty buffer. Though such is not legal
00294         // it is supported by some compilers, so we must ensure it cannot be
00295         // so
00296         stlsoft_static_assert(0 != space);
00297 
00298         // These assertions ensure that the member ordering is not
00299         // changed, invalidating the initialisation logic of m_buffer and
00300         // m_cItems. The runtime assert is included for those compilers that
00301         // do not implement compile-time asserts.
00302         stlsoft_static_assert(stlsoft_raw_offsetof(class_type, m_buffer) < stlsoft_raw_offsetof(class_type, m_cItems));
00303 #if defined(__STLSOFT_COMPILER_IS_WATCOM)
00304         stlsoft_assert(stlsoft_raw_offsetof(class_type, m_buffer) < stlsoft_raw_offsetof(class_type, m_cItems));
00305 #else
00306         stlsoft_message_assert("m_buffer must be before m_cItems in the auto_buffer definition", stlsoft_raw_offsetof(class_type, m_buffer) < stlsoft_raw_offsetof(class_type, m_cItems));
00307 #endif /* !__STLSOFT_COMPILER_IS_WATCOM */
00308 
00309 #ifndef _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
00310         // Use the must_be_pod constraint to ensure that
00311         // no type is managed in auto_buffer which would result in
00312         // dangerous mismanagement of the lifetime of its instances.
00313         //
00314         // Preprocessor specification of _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
00315         // prevents this, but the natural rules of the language will
00316         // still prevent non POD types being placed in m_internal[].
00317         stlsoft_constraint_must_be_pod(value_type);
00318 #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD */
00319     }
00325 #if defined(__STLSOFT_CF_EXCEPTION_SIGNATURE_SUPPORT)
00326     ~auto_buffer()
00327 #else /* ? compiler */
00328     ~auto_buffer() stlsoft_throw_0()
00329 #endif /* compiler */
00330     {
00331         if(space < m_cItems)
00332         {
00333             stlsoft_assert(NULL != m_buffer);
00334 
00335             deallocate_(m_buffer, m_cItems);
00336         }
00337     }
00339 
00341 
00342 public:
00355     ss_bool_t resize(size_type cItems)
00356     {
00357         // There are four changes possible:
00358         //
00359         // 1. Expansion within the internal buffer
00360         // 2. Contraction within the internal buffer
00361         // 3. Expansion from the internal buffer to an allocated buffer
00362         // 4. Contraction from an allocated buffer to the internal buffer
00363         // 5. Expansion from the allocated buffer to another allocated buffer
00364         // 6. Contraction from the allocated buffer to another allocated buffer
00365 
00366         if(m_cItems < cItems)
00367         {
00368             // Expansion; cases 1, 3 & 5
00369 
00370             if(space < m_cItems)
00371             {
00372                 // Current buffer is allocated: case 5
00373                 pointer new_buffer  =   reallocate_(m_buffer, m_cItems, cItems);
00374 
00375                 // Still test for NULL here, since some allocators will
00376                 // not throw bad_alloc.
00377                 if(NULL == new_buffer)
00378                 {
00379                     return false;
00380                 }
00381 
00382                 // Now repoint to the new buffer
00383                 m_buffer = new_buffer;
00384             }
00385             else
00386             {
00387                 // Expanding from internal buffer; cases 1 & 3
00388 
00389                 if(space < cItems)
00390                 {
00391                     // Expanding to allocated buffer; case 3
00392 
00393                     pointer new_buffer = allocate_(cItems);
00394 
00395                     // Still test for NULL here, since some allocators will
00396                     // not throw bad_alloc.
00397                     if(NULL == new_buffer)
00398                     {
00399                         return false;
00400                     }
00401 
00402                     if(0 != m_cItems)
00403                     {
00404                         block_copy(new_buffer, m_buffer, m_cItems);
00405                     }
00406                     m_buffer = new_buffer;
00407                 }
00408                 else
00409                 {
00410                     // Expanding to internal buffer; case 1
00411 
00412                     // Nothing to do
00413                     stlsoft_assert(!(space < cItems));
00414                 }
00415             }
00416         }
00417         else
00418         {
00419             // Contraction; cases 2, 4 & 6
00420 
00421             if(space < m_cItems)
00422             {
00423                 // Current buffer is allocated: cases 4 & 6
00424 
00425                 if(space < cItems)
00426                 {
00427                     // Contracting within allocated buffer; case 6
00428 
00429                     // Nothing to do
00430                     stlsoft_assert(space < cItems);
00431                 }
00432                 else
00433                 {
00434                     // Contracting back to internal; case 4
00435 
00436                     if(0 != cItems)
00437                     {
00438                         block_copy(const_cast<pointer>(&m_internal[0]), m_buffer, cItems);
00439                     }
00440 
00441                     deallocate_(m_buffer, m_cItems);
00442 
00443                     m_buffer = const_cast<pointer>(&m_internal[0]);
00444                 }
00445             }
00446             else
00447             {
00448                 // Current buffer is internal; case 2
00449 
00450                 // Nothing to do
00451                 stlsoft_assert(!(space < cItems));
00452             }
00453         }
00454 
00455         m_cItems = cItems;
00456 
00457         return true;
00458     }
00459 
00465     void swap(class_type &rhs)
00466     {
00467         if( space < m_cItems &&
00468             space < rhs.m_cItems)
00469         {
00470             // Both are allocated, so just swap them
00471             swap_(m_buffer, rhs.m_buffer);
00472         }
00473         else if(space < m_cItems)
00474         {
00475             // *this is allocated on the heap, rhs is using m_internal
00476 
00477             // 1. Copy the contents of rhs.m_internal to this->m_internal
00478             block_copy(&m_internal[0], &rhs.m_internal[0], rhs.m_cItems);
00479 
00480             // 2. Move m_buffer from *this to rhs
00481             rhs.m_buffer = m_buffer;
00482 
00483             // 3. Tell *this to use its internal buffer
00484             m_buffer = &m_internal[0];
00485         }
00486         else if(space < rhs.m_cItems)
00487         {
00488             // This is a lazy cheat.
00489             rhs.swap(*this);
00490 
00491             return;
00492         }
00493         else
00494         {
00495             // Both are using internal buffers, so we exchange the contents
00496             value_type  t[space];
00497 
00498             block_copy(&t[0], &rhs.m_internal[0], rhs.m_cItems);
00499             block_copy(&rhs.m_internal[0], &m_internal[0], m_cItems);
00500             block_copy(&m_internal[0], &t[0], rhs.m_cItems);
00501         }
00502 
00503         swap_(m_cItems, rhs.m_cItems);
00504     }
00506 
00508 
00509 public:
00510     // Note: The following two const and non-const implicit conversion
00511     // operators are correctly implemented. However, GCC will pedantically
00512     // give a verbose warning describing its having selected one over the
00513     // other, and this is, in current versions of the compiler, not
00514     // suppressable. The warnings must, alas, simply be ignored.
00515 
00517     operator pointer ()
00518     {
00519         return m_buffer;
00520     }
00521 
00522 #ifdef _STLSOFT_AUTO_BUFFER_ALLOW_CONST_CONVERSION_OPERATOR
00523 
00524     operator const_pointer () const
00525     {
00526         return m_buffer;
00527     }
00528 #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_CONST_CONVERSION_OPERATOR */
00529 
00530 
00533 public:
00535     pointer data()
00536     {
00537         return m_buffer;
00538     }
00540     const_pointer data() const
00541     {
00542         return m_buffer;
00543     }
00545 
00547 
00548 public:
00550     const_iterator begin() const
00551     {
00552         return m_buffer;
00553     }
00561     const_iterator end() const
00562     {
00563         return m_buffer + m_cItems;
00564     }
00565 
00567     iterator begin()
00568     {
00569         return m_buffer;
00570     }
00578     iterator end()
00579     {
00580         return m_buffer + m_cItems;
00581     }
00582 
00583 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00587     const_reverse_iterator rbegin() const
00588     {
00589         return const_reverse_iterator(end());
00590     }
00594     const_reverse_iterator rend() const
00595     {
00596         return const_reverse_iterator(begin());
00597     }
00601     reverse_iterator  rbegin()
00602     {
00603         return reverse_iterator(end());
00604     }
00608     reverse_iterator  rend()
00609     {
00610         return reverse_iterator(begin());
00611     }
00612 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00613 
00615 
00617 
00618 public:
00626     size_type size() const
00627     {
00628         return m_cItems;
00629     }
00630 
00632     static size_type internal_size()
00633     {
00634         return space;
00635     }
00636 
00641     ss_bool_t empty() const
00642     {
00643         return 0 == m_cItems;
00644     }
00645 
00646 #if defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE)
00647     static allocator_type &get_allocator()
00648     {
00649         static allocator_type   s_allocator;
00650 
00651         return s_allocator;
00652     }
00653 #else /* ? STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
00654     allocator_type get_allocator() const
00655     {
00656         return *this;
00657     }
00658 #endif /* STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
00659 
00661 
00663 
00664 private:
00665     pointer     m_buffer;           // Pointer to used buffer
00666     size_type   m_cItems;           // Number of items in buffer
00667     value_type  m_internal[space];  // Internal storage
00669 
00670 // Not to be implemented
00671 private:
00672     auto_buffer(class_type const &rhs);
00673     auto_buffer const &operator =(class_type const &rhs);
00674 };
00675 
00676 /* 
00677  * Shims
00678  */
00679 
00680 #ifndef __STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED
00681 
00682 template<   ss_typename_param_k T
00683         ,   ss_typename_param_k A
00684         ,   ss_size_t           SPACE
00685         >
00686 inline ss_bool_t is_empty(auto_buffer<T, A, SPACE> const &b)
00687 {
00688     return b.empty();
00689 }
00690 
00691 #endif /* !__STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED */
00692 
00694 // Unit-testing
00695 
00696 #ifdef STLSOFT_UNITTEST
00697 
00698 namespace unittest
00699 {
00700     ss_bool_t test_stlsoft_auto_buffer(unittest_reporter *r)
00701     {
00702         ss_bool_t               bSuccess    =   true;
00703 
00704         unittest_initialiser    init(r, "STLSoft", "auto_buffer", __FILE__);
00705 
00706         typedef auto_buffer<int, new_allocator<int>, 16>    buffer_t;
00707 
00708         buffer_t    buffer1(10);
00709         buffer_t    buffer2(100);
00710 
00711         /* Check that resizing within the internal_size() does not
00712          * change the pointer.
00713          */
00714         int *pi = buffer1.data();
00715 
00716         for(ss_size_t c = 1; bSuccess && c < buffer1.internal_size(); ++c)
00717         {
00718             buffer1.resize(c);
00719 
00720             if(pi != buffer1.data())
00721             {
00722                 r->report("auto_buffer resize not allocated from internal buffer: failed ", __LINE__);
00723                 bSuccess = false;
00724             }
00725         }
00726 
00727 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00728         /* Check that forward and backward iteration provide the same result. */
00729         int total_forward   =   stlsoft_ns_qual_std(accumulate)(buffer2.begin(), buffer2.end(), 0);
00730         int total_backward  =   stlsoft_ns_qual_std(accumulate)(buffer2.rbegin(), buffer2.rend(), 0);
00731 
00732         if(total_forward != total_backward)
00733         {
00734             r->report("Forward and backward enumeration equivalence failed ", __LINE__);
00735             bSuccess = false;
00736         }
00737 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00738 
00739         return bSuccess;
00740     }
00741 
00742     unittest_registrar    unittest_stlsoft_auto_buffer(test_stlsoft_auto_buffer);
00743 
00744 } // namespace unittest
00745 
00746 #endif /* STLSOFT_UNITTEST */
00747 
00748 /* 
00749 
00750 #ifndef _STLSOFT_NO_NAMESPACE
00751 } // namespace stlsoft
00752 #endif /* _STLSOFT_NO_NAMESPACE */
00753 
00754 /* 
00755 
00756 #endif /* !STLSOFT_INCL_H_STLSOFT_AUTO_BUFFER */
00757 
00758 /* 

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