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 
00041 
00042 
00043 
00044 
00045 
00053 #ifndef MFCSTL_INCL_MFCSTL_COLLECTIONS_HPP_CARRAY_ADAPTORS
00054 #define MFCSTL_INCL_MFCSTL_COLLECTIONS_HPP_CARRAY_ADAPTORS
00055 
00056 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00057 # define MFCSTL_VER_MFCSTL_COLLECTIONS_HPP_CARRAY_ADAPTORS_MAJOR    4
00058 # define MFCSTL_VER_MFCSTL_COLLECTIONS_HPP_CARRAY_ADAPTORS_MINOR    2
00059 # define MFCSTL_VER_MFCSTL_COLLECTIONS_HPP_CARRAY_ADAPTORS_REVISION 1
00060 # define MFCSTL_VER_MFCSTL_COLLECTIONS_HPP_CARRAY_ADAPTORS_EDIT     82
00061 #endif 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 #ifndef MFCSTL_INCL_MFCSTL_HPP_MFCSTL
00078 # include <mfcstl/mfcstl.hpp>
00079 #endif 
00080 #ifndef MFCSTL_INCL_MFCSTL_MEMORY_HPP_AFX_ALLOCATOR
00081 # include <mfcstl/memory/afx_allocator.hpp>
00082 #endif 
00083 #ifndef MFCSTL_INCL_MFCSTL_COLLECTIONS_HPP_CARRAY_SWAP
00084 # include <mfcstl/collections/carray_swap.hpp>
00085 #endif 
00086 #ifndef MFCSTL_INCL_MFCSTL_COLLECTIONS_HPP_CARRAY_TRAITS
00087 # include <mfcstl/collections/carray_traits.hpp>
00088 #endif 
00089 #ifndef MFCSTL_INCL_MFCSTL_UTIL_HPP_MEMORY_EXCEPTION_TRANSLATION_POLICIES
00090 # include <mfcstl/util/memory_exception_translation_policies.hpp>
00091 #endif 
00092 #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_GENERATORS
00093 # include <stlsoft/util/std/iterator_generators.hpp>
00094 #endif 
00095 #ifndef STLSOFT_INCL_STLSOFT_META_HPP_CAPABILITIES
00096 # include <stlsoft/meta/capabilities.hpp>
00097 #endif 
00098 #ifdef STLSOFT_META_HAS_IS_SAME_TYPE
00099 # ifndef STLSOFT_INCL_STLSOFT_META_HPP_IS_SAME_TYPE
00100 #  include <stlsoft/meta/is_same_type.hpp>
00101 # endif 
00102 #endif 
00103 #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
00104 # include <stlsoft/collections/util/collections.hpp>
00105 #endif 
00106 #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
00107 # include <stlsoft/util/std/iterator_helper.hpp>
00108 #endif 
00109 
00110 #if defined(STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT) && \
00111     !defined(MFCSTL_NO_INCLUDE_AFXTEMPL_BY_DEFAULT)
00112 # include <afxtempl.h>
00113 #endif 
00114 
00115 #ifndef STLSOFT_INCL_ALGORITHM
00116 # define STLSOFT_INCL_ALGORITHM
00117 # include <algorithm>
00118 #endif 
00119 
00120 #ifdef STLSOFT_UNITTEST
00121 # include <afxtempl.h>
00122 # include <stlsoft/string/simple_string.hpp>
00123 #endif 
00124 
00125 
00126 
00127 
00128 
00129 #ifndef _MFCSTL_NO_NAMESPACE
00130 # if defined(_STLSOFT_NO_NAMESPACE) || \
00131      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00132 
00133 namespace mfcstl
00134 {
00135 # else
00136 
00137 
00138 namespace stlsoft
00139 {
00140 
00141 namespace mfcstl_project
00142 {
00143 
00144 # endif 
00145 #endif 
00146 
00147 
00148 
00149 
00150 
00151 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00152 
00153 template<   ss_typename_param_k A
00154         ,   ss_typename_param_k I
00155         ,   ss_typename_param_k T
00156         >
00157 class CArray_adaptor_base;
00158 
00159 template<   ss_typename_param_k A
00160         ,   ss_typename_param_k T
00161         >
00162 class CArray_cadaptor;
00163 
00164 template<   ss_typename_param_k A
00165         ,   ss_typename_param_k T
00166         >
00167 class CArray_iadaptor;
00168 
00169 #endif 
00170 
00184 template<   ss_typename_param_k A
00185         ,   ss_typename_param_k I
00186         ,   ss_typename_param_k T
00187         >
00188 class CArray_adaptor_base
00189     : public stlsoft_ns_qual(stl_collection_tag)
00190 {
00193 public:
00195     typedef A                                                                   array_type;
00196 private:
00197     typedef I                                                                   interface_class_type;
00198     typedef T                                                                   array_traits_type;
00199 #if defined(MFCSTL_CARRAY_ADAPTORS_USE_BAD_ALLOC_POLICY)
00200     typedef bad_alloc_throwing_policy                                           exception_translation_policy_type;
00201 #else 
00202     typedef CMemoryException_throwing_policy                                    exception_translation_policy_type;
00203 #endif 
00204 public:
00209     typedef ss_typename_type_k array_traits_type::value_type                    value_type;
00211     typedef afx_allocator<value_type>                                           allocator_type;
00213     typedef ss_typename_type_k allocator_type::reference                        reference;
00215     typedef ss_typename_type_k allocator_type::const_reference                  const_reference;
00217     typedef ss_typename_type_k allocator_type::pointer                          pointer;
00219     typedef ss_typename_type_k allocator_type::const_pointer                    const_pointer;
00221     typedef
00222 # if !defined(STLSOFT_COMPILER_IS_BORLAND)
00223            ss_typename_type_k
00224 # endif 
00225                        pointer_iterator <   value_type
00226                                         ,   pointer
00227                                         ,   reference
00228                                         >::type                                 iterator;
00230     typedef
00231 # if !defined(STLSOFT_COMPILER_IS_BORLAND)
00232          ss_typename_type_k
00233 # endif 
00234                        pointer_iterator <   value_type const
00235                                         ,   const_pointer
00236                                         ,   const_reference
00237                                         >::type                                 const_iterator;
00239     typedef ms_size_t                                                           size_type;
00241     typedef ms_ptrdiff_t                                                        difference_type;
00243     typedef CArray_adaptor_base<A, I, T>                                        class_type;
00244 #ifdef STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT
00246     typedef ss_typename_type_k reverse_iterator_generator   <   iterator
00247                                                             ,   value_type
00248                                                             ,   reference
00249                                                             ,   pointer
00250                                                             ,   difference_type
00251                                                             >::type             reverse_iterator;
00252 
00254     typedef ss_typename_type_k const_reverse_iterator_generator <   const_iterator
00255                                                             ,   value_type
00256                                                             ,   const_reference
00257                                                             ,   const_pointer
00258                                                             ,   difference_type
00259                                                             >::type             const_reverse_iterator;
00260 #endif 
00262 
00265 protected:
00266     enum { growthGranularity =  16 };
00267 
00268     static size_type calc_increment_(size_type n)
00269     {
00270         size_type   numBlocks   =   n / growthGranularity;
00271 
00272         return (1 + numBlocks) * growthGranularity;
00273     }
00275 
00278 public:
00280     array_type          &get_CArray()
00281     {
00282         return static_cast<interface_class_type*>(this)->get_actual_array();
00283     }
00285     array_type const    &get_CArray() const
00286     {
00287         return static_cast<interface_class_type const*>(this)->get_actual_array();
00288     }
00290 
00293 protected:
00298     CArray_adaptor_base()
00299     {}
00301     ~CArray_adaptor_base() stlsoft_throw_0()
00302     {}
00303 public:
00305     allocator_type get_allocator() const
00306     {
00307         return allocator_type();
00308     }
00309 #if defined(_DEBUG) || \
00310     defined(MFCSTL_ARRAY_ADAPTORS_ALLOW_CAPACITY_PEEK)
00311 public:
00312 #else 
00313 protected:
00314 #endif 
00315     size_type grow_increment() const
00316     {
00317         class GrowByGetter
00318             : public array_type
00319         {
00320         public:
00321             size_type grow_increment() const
00322             {
00323                 return m_nGrowBy;
00324             }
00325         };
00326 
00327         return static_cast<GrowByGetter const&>(get_CArray()).grow_increment();
00328     }
00329     size_type capacity() const
00330     {
00331         class CapacityGetter
00332             : public array_type
00333         {
00334         public:
00335             size_type capacity() const
00336             {
00337                 return m_nMaxSize;
00338             }
00339         };
00340 
00341         return static_cast<CapacityGetter const&>(get_CArray()).capacity();
00342     }
00344 
00347 public:
00356     void assign(size_type n, value_type const& value)
00357     {
00358 #ifdef MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT
00359         try
00360         {
00361             array_type  ar;
00362 
00363             ar.SetSize(0, calc_increment_(n));
00364             if(n > 0) 
00365             {
00366                 ar.InsertAt(0, value, static_cast<int>(n));
00367             }
00368             CArray_swap(this->get_CArray(), ar);
00369         }
00370         catch(CMemoryException *px)
00371         {
00372             exception_translation_policy_type::handle(px);
00373         }
00374         catch(mfcstl_ns_qual_std(bad_alloc) &x)
00375         {
00376             exception_translation_policy_type::handle(x);
00377         }
00378 #else 
00379 
00380 
00381 
00382 
00383 
00384         resize(n);
00385         mfcstl_ns_qual_std(fill_n)(begin(), n, value);
00386 #endif 
00387 
00388         
00389         MFCSTL_ASSERT(size() == n);
00390     }
00391 
00400     template <ss_typename_param_k I2>
00401     void assign(I2 first, I2 last)
00402     {
00403         
00404         MFCSTL_ASSERT(is_valid_source_range_(first, last));
00405 
00406 #ifdef MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT
00407         if(empty())
00408         {
00409             
00410             
00411             
00412             try
00413             {
00414                 clear_and_assign_(first, last);
00415             }
00416             catch(...)
00417             {
00418                 clear();
00419 
00420                 throw;
00421             }
00422         }
00423         else
00424         {
00425             
00426             
00427             array_type                  ar;
00428             CArray_iadaptor<array_type
00429                         ,   array_traits_type
00430                         >               arp(ar);
00431             arp.assign(first, last);
00432 
00433             CArray_swap(this->get_CArray(), ar);
00434         }
00435 #else 
00436         clear_and_assign_(first, last);
00437 #endif 
00438     }
00440 
00443 public:
00445     size_type size() const
00446     {
00447         return static_cast<size_type>(get_CArray().GetSize());
00448     }
00450     size_type max_size() const
00451     {
00452         return get_allocator().max_size();
00453     }
00455     ms_bool_t empty() const
00456     {
00457         return 0 == size();
00458     }
00465     void resize(size_type n)
00466     {
00467         try
00468         {
00469             get_CArray().SetSize(n, calc_increment_(n));
00470         }
00471         catch(CMemoryException *px)
00472         {
00473             exception_translation_policy_type::handle(px);
00474         }
00475         catch(mfcstl_ns_qual_std(bad_alloc) &x)
00476         {
00477             exception_translation_policy_type::handle(x);
00478         }
00479 
00480         
00481         MFCSTL_ASSERT(size() == n);
00482     }
00494     void resize(size_type n, value_type value)
00495     {
00496         const size_type oldSize = size();
00497         resize(n);
00498         if(oldSize < n)
00499         {
00500             try
00501             {
00502                 mfcstl_ns_qual_std(fill_n)(begin() + oldSize, n - oldSize, value);
00503             }
00504             catch(...)
00505             {
00506                 resize(oldSize);
00507                 throw;
00508             }
00509         }
00510     }
00512 
00515 public:
00521     reference operator [](size_type n)
00522     {
00523         MFCSTL_MESSAGE_ASSERT("index out of bounds", n < size());
00524 
00525         return get_CArray()[n];
00526     }
00532     const_reference operator [](size_type n) const
00533     {
00534         MFCSTL_MESSAGE_ASSERT("index out of bounds", n < size());
00535 
00536         return get_CArray()[n];
00537     }
00542     reference at(size_type n)
00543     {
00544         if(n >= size())
00545         {
00546             STLSOFT_THROW_X(mfcstl_ns_qual_std(out_of_range)("Invalid index specified"));
00547         }
00548 
00549         return (*this)[n];
00550     }
00555     const_reference at(size_type n) const
00556     {
00557         if(n >= size())
00558         {
00559             STLSOFT_THROW_X(mfcstl_ns_qual_std(out_of_range)("Invalid index specified"));
00560         }
00561         return (*this)[n];
00562     }
00564     reference front()
00565     {
00566         MFCSTL_MESSAGE_ASSERT("front() called on an empty instance", !empty());
00567 
00568         return (*this)[0];
00569     }
00571     reference back()
00572     {
00573         MFCSTL_MESSAGE_ASSERT("back() called on an empty instance", !empty());
00574 
00575         return (*this)[size() - 1];
00576     }
00578     const_reference front() const
00579     {
00580         MFCSTL_MESSAGE_ASSERT("front() called on an empty instance", !empty());
00581 
00582         return (*this)[0];
00583     }
00585     const_reference back() const
00586     {
00587         MFCSTL_MESSAGE_ASSERT("back() called on an empty instance", !empty());
00588 
00589         return (*this)[size() - 1];
00590     }
00592 
00595 public:
00597     iterator begin()
00598     {
00599         return get_CArray().GetData();
00600     }
00602     iterator end()
00603     {
00604         return begin() + size();
00605     }
00607     const_iterator begin() const
00608     {
00609         
00610         value_type const    *p1 =   get_CArray().GetData();
00611         value_type *const   p2  =   const_cast<value_type *const>(p1);
00612 
00613         return p2;
00614     }
00616     const_iterator end() const
00617     {
00618         return begin() + size();
00619     }
00620 #ifdef STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT
00622     reverse_iterator rbegin()
00623     {
00624         return reverse_iterator(end());
00625     }
00627     reverse_iterator rend()
00628     {
00629         return reverse_iterator(begin());
00630     }
00632     const_reverse_iterator rbegin() const
00633     {
00634         return const_reverse_iterator(end());
00635     }
00637     const_reverse_iterator rend() const
00638     {
00639         return const_reverse_iterator(begin());
00640     }
00641 #endif 
00643 
00646 public:
00647     template<   ss_typename_param_k A2
00648             ,   ss_typename_param_k I2
00649             ,   ss_typename_param_k T2
00650             >
00651     ms_bool_t equal(CArray_adaptor_base<A2, I2, T2> const& rhs) const
00652     {
00653         typedef CArray_adaptor_base<A2, I2, T2>         rhs_t;
00654         typedef ss_typename_type_k rhs_t::value_type    rhs_value_t;
00655 
00656         STLSOFT_STATIC_ASSERT(sizeof(value_type) == sizeof(ss_typename_type_k rhs_t::value_type));
00657 
00658 #ifdef STLSOFT_META_HAS_IS_SAME_TYPE
00659         STLSOFT_STATIC_ASSERT((stlsoft::is_same_type<value_type, rhs_value_t>::value));
00660 #endif 
00661 
00662         return size() == rhs.size() && stlsoft_ns_qual_std(equal)(begin(), end(), rhs.begin());
00663     }
00664 
00665     ms_bool_t equal(array_type const& rhs) const
00666     {
00667         array_type const    &lhs    =   this->get_CArray();
00668 
00669         return lhs.GetSize() == rhs.GetSize() && stlsoft_ns_qual_std(equal)(begin(), end(), rhs.GetData());
00670     }
00671 
00672     template<   ss_typename_param_k A2
00673             ,   ss_typename_param_k I2
00674             ,   ss_typename_param_k T2
00675             >
00676     ms_bool_t less_than(CArray_adaptor_base<A2, I2, T2> const& rhs) const
00677     {
00678         typedef CArray_adaptor_base<A2, I2, T2>         rhs_t;
00679         typedef ss_typename_type_k rhs_t::value_type    rhs_value_t;
00680 
00681         STLSOFT_STATIC_ASSERT(sizeof(value_type) == sizeof(ss_typename_type_k rhs_t::value_type));
00682 
00683 #ifdef STLSOFT_META_HAS_IS_SAME_TYPE
00684         STLSOFT_STATIC_ASSERT((stlsoft::is_same_type<value_type, rhs_value_t>::value));
00685 #endif 
00686 
00687         return stlsoft_ns_qual_std(lexicographical_compare)(begin(), end(), rhs.begin(), rhs.end());
00688     }
00689 
00690     ms_bool_t less_than(array_type const& rhs) const
00691     {
00692         return stlsoft_ns_qual_std(lexicographical_compare)(begin(), end(), rhs.GetData(), rhs.GetData() + rhs.GetSize());
00693     }
00694 
00695     template<   ss_typename_param_k A2
00696             ,   ss_typename_param_k I2
00697             ,   ss_typename_param_k T2
00698             >
00699     ms_bool_t greater_than(CArray_adaptor_base<A2, I2, T2> const& rhs) const
00700     {
00701         typedef CArray_adaptor_base<A2, I2, T2>         rhs_t;
00702         typedef ss_typename_type_k rhs_t::value_type    rhs_value_t;
00703 
00704         STLSOFT_STATIC_ASSERT(sizeof(value_type) == sizeof(ss_typename_type_k rhs_t::value_type));
00705 
00706 #ifdef STLSOFT_META_HAS_IS_SAME_TYPE
00707         STLSOFT_STATIC_ASSERT((stlsoft::is_same_type<value_type, rhs_value_t>::value));
00708 #endif 
00709 
00710         return stlsoft_ns_qual_std(lexicographical_compare)(rhs.begin(), rhs.end(), begin(), end());
00711     }
00712 
00713     ms_bool_t greater_than(array_type const& rhs) const
00714     {
00715         return stlsoft_ns_qual_std(lexicographical_compare)(rhs.GetData(), rhs.GetData() + rhs.GetSize(), begin(), end());
00716     }
00718 
00721 public:
00727     void push_back(value_type const& value)
00728     {
00729         const size_type oldSize =   size();
00730 
00731         resize(size());
00732 
00733         try
00734         {
00735             try
00736             {
00737                 get_CArray().Add(value);
00738             }
00739             catch(CMemoryException *px)
00740             {
00741                 exception_translation_policy_type::handle(px);
00742             }
00743             catch(mfcstl_ns_qual_std(bad_alloc) &x)
00744             {
00745                 exception_translation_policy_type::handle(x);
00746             }
00747         }
00748         catch(...)
00749         {
00750             if(size() != oldSize)
00751             {
00752                 MFCSTL_ASSERT(size() == oldSize + 1);
00753 
00754                 resize(oldSize);
00755             }
00756 
00757             throw;
00758         }
00759     }
00763     void pop_back() stlsoft_throw_0()
00764     {
00765         
00766         MFCSTL_MESSAGE_ASSERT("pop_back() called on empty container", !empty());
00767 
00768         get_CArray().RemoveAt(get_CArray().GetUpperBound());
00769     }
00785     iterator insert(iterator pos, value_type const& value)
00786     {
00787         
00788         MFCSTL_ASSERT(pos == end() || (pos >= begin() && pos < end()));
00789 
00790         difference_type index   =   pos - begin();
00791         const size_type oldSize =   size();
00792 
00793         resize(size());
00794 
00795         try
00796         {
00797             try
00798             {
00799                 get_CArray().InsertAt(static_cast<int>(index), value, 1);
00800             }
00801             catch(CMemoryException *px)
00802             {
00803                 exception_translation_policy_type::handle(px);
00804             }
00805             catch(mfcstl_ns_qual_std(bad_alloc) &x)
00806             {
00807                 exception_translation_policy_type::handle(x);
00808             }
00809         }
00810         catch(...)
00811         {
00812             if(size() != oldSize)
00813             {
00814                 MFCSTL_ASSERT(size() == oldSize + 1);
00815 
00816                 get_CArray().RemoveAt(static_cast<int>(index), 1);
00817             }
00818 
00819             throw;
00820         }
00821 
00822         return begin() + index;
00823     }
00838     void insert(iterator pos, size_type n, value_type const& value)
00839     {
00840         
00841         MFCSTL_ASSERT(pos == end() || (pos >= begin() && pos < end()));
00842 
00843         difference_type index = pos - begin();
00844 
00845         if(empty())
00846         {
00847             MFCSTL_ASSERT(0 == index);
00848 
00849             assign(n, value);
00850         }
00851         else
00852         {
00853             const size_type oldSize =   size();
00854 
00855             resize(size());
00856 
00857             try
00858             {
00859                 try
00860                 {
00861                     if(n > 0) 
00862                     {
00863                         get_CArray().InsertAt(static_cast<int>(index), value, n);
00864                     }
00865                 }
00866                 catch(CMemoryException *px)
00867                 {
00868                     exception_translation_policy_type::handle(px);
00869                 }
00870                 catch(mfcstl_ns_qual_std(bad_alloc) &x)
00871                 {
00872                     exception_translation_policy_type::handle(x);
00873                 }
00874             }
00875             catch(...)
00876             {
00877                 if(size() != oldSize)
00878                 {
00879                     MFCSTL_ASSERT(size() == oldSize + n);
00880 
00881                     get_CArray().RemoveAt(static_cast<int>(index), size() - oldSize);
00882                 }
00883 
00884                 throw;
00885             }
00886         }
00887     }
00902     template <ss_typename_param_k I2>
00903     void insert(iterator pos, I2 first, I2 last)
00904     {
00905         
00906         MFCSTL_ASSERT(is_valid_source_range_(first, last));
00907         MFCSTL_ASSERT(pos == end() || (pos >= begin() && pos < end()));
00908 
00909         array_type                  ar;
00910         CArray_iadaptor<array_type
00911                     ,   array_traits_type
00912                     >               arp(ar);
00913         arp.assign(first, last);
00914         difference_type             index   =   pos - begin();
00915         const size_type             oldSize =   size();
00916         const size_type             n       =   arp.size();
00917 
00918         resize(size());
00919 
00920         try
00921         {
00922             try
00923             {
00924                 get_CArray().InsertAt(static_cast<int>(index), &ar);
00925             }
00926             catch(CMemoryException *px)
00927             {
00928                 exception_translation_policy_type::handle(px);
00929             }
00930             catch(mfcstl_ns_qual_std(bad_alloc) &x)
00931             {
00932                 exception_translation_policy_type::handle(x);
00933             }
00934         }
00935         catch(...)
00936         {
00937             if(size() != oldSize)
00938             {
00939                 MFCSTL_ASSERT(size() == oldSize + n);
00940 
00941                 get_CArray().RemoveAt(static_cast<int>(index), size() - oldSize);
00942             }
00943 
00944             throw;
00945         }
00946     }
00961     iterator erase(iterator pos) stlsoft_throw_0()
00962     {
00963         
00964         MFCSTL_ASSERT(pos == end() || (pos >= begin() && pos < end()));
00965 
00966         difference_type index = pos - begin();
00967         get_CArray().RemoveAt(static_cast<int>(index), 1);
00968 
00969         
00970         MFCSTL_ASSERT(pos == begin() + index);
00971 
00972         resize(size());
00973 
00974         return pos;
00975     }
00991     iterator erase(iterator first, iterator last) stlsoft_throw_0()
00992     {
00993         
00994         MFCSTL_ASSERT(first <= last);
00995         MFCSTL_ASSERT(first == end() || (first >= begin() && first < end()));
00996         MFCSTL_ASSERT(last == end() || (last >= begin() && last < end()));
00997 
00998         difference_type index = first - begin();
00999         get_CArray().RemoveAt(static_cast<int>(index), mfcstl_ns_qual_std(distance)(first, last));
01000 
01001         
01002         MFCSTL_ASSERT(first == begin() + index);
01003 
01004         resize(size());
01005 
01006         return first;
01007     }
01009     void clear() stlsoft_throw_0()
01010     {
01011         get_CArray().RemoveAll();
01012 
01013         resize(size());
01014     }
01015 
01016 #ifdef MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT
01024     void swap(class_type& rhs) stlsoft_throw_0()
01025     {
01026         mfcstl::CArray_swap(this->get_CArray(), rhs.get_CArray());
01027     }
01028 #endif 
01029 
01034     void         swap_by_copy(class_type& rhs)
01035     {
01036         class_type  t       =   rhs;
01037                     rhs     =   *this;
01038                     *this   =   t;
01039     }
01041 
01044 private:
01045     template <ss_typename_param_k I2>
01046 # if defined(STLSOFT_COMPILER_IS_MWERKS)
01047     
01048     void clear_and_assign_(I2 first, I2 last, stlsoft_ns_qual_std(input_iterator_tag) const*)
01049 # else 
01050     void clear_and_assign_(I2 first, I2 last, stlsoft_ns_qual_std(input_iterator_tag))
01051 # endif 
01052     {
01053         clear();
01054 
01055         mfcstl_ns_qual_std(copy)(first, last, mfcstl_ns_qual_std(back_inserter)<class_type>(*this));
01056     }
01057     template <ss_typename_param_k I2>
01058 # if defined(STLSOFT_COMPILER_IS_MWERKS)
01059     
01060     void clear_and_assign_(I2 first, I2 last, stlsoft_ns_qual_std(forward_iterator_tag) const*)
01061 # else 
01062     void clear_and_assign_(I2 first, I2 last, stlsoft_ns_qual_std(forward_iterator_tag))
01063 # endif 
01064     {
01065         resize(mfcstl_ns_qual_std(distance)(first, last));
01066 
01067         mfcstl_ns_qual_std(copy)(first, last, begin());
01068     }
01069 
01070     template <ss_typename_param_k I2>
01071     void clear_and_assign_(I2 first, I2 last)
01072     {
01073 # if defined(STLSOFT_COMPILER_IS_GCC) && \
01074      __GNUC__ < 3
01075         typedef ss_typename_type_k mfcstl_ns_qual_std(iterator_traits)<I2> traits_t;
01076 
01077         clear_and_assign_(first, last, traits_t::iterator_category());
01078 # elif defined(STLSOFT_COMPILER_IS_MWERKS)
01079         clear_and_assign_(first, last, stlsoft_iterator_query_category_ptr(I2, first));
01080 # else 
01081         clear_and_assign_(first, last, stlsoft_iterator_query_category(I2, first));
01082 # endif 
01083     }
01084 
01085 protected:
01086 #if (   !defined(STLSOFT_COMPILER_IS_MSVC) || \
01087         _MSC_VER > 1200)
01088     template <ss_typename_param_k I2>
01089 # if defined(STLSOFT_COMPILER_IS_MWERKS)
01090     
01091     static ms_bool_t is_valid_source_range_(I2 first, I2 last, stlsoft_ns_qual_std(input_iterator_tag) const*)
01092 # else 
01093     static ms_bool_t is_valid_source_range_(I2 first, I2 last, stlsoft_ns_qual_std(input_iterator_tag))
01094 # endif 
01095     {
01096         return true;    
01097     }
01098 #endif 
01099 
01100     template<   ss_typename_param_k I2
01101             ,   ss_typename_param_k T2
01102             >
01103     static ms_bool_t is_valid_source_range_(I2 first, I2 last, T2)
01104     {
01105         return true;    
01106     }
01107 
01108 #if (   !defined(STLSOFT_COMPILER_IS_MSVC) || \
01109         _MSC_VER > 1200)
01110     template <ss_typename_param_k I2>
01111 # if defined(STLSOFT_COMPILER_IS_MWERKS)
01112     
01113     static ms_bool_t is_valid_source_range_(I2 first, I2 last, stlsoft_ns_qual_std(random_access_iterator_tag) const*)
01114 # else 
01115     static ms_bool_t is_valid_source_range_(I2 first, I2 last, stlsoft_ns_qual_std(random_access_iterator_tag))
01116 # endif 
01117     {
01118         return first <= last;
01119     }
01120 #endif 
01121 
01122     template <ss_typename_param_k I2>
01123     static ms_bool_t is_valid_source_range_(I2 first, I2 last)
01124     {
01125 # if defined(STLSOFT_COMPILER_IS_GCC) && \
01126      __GNUC__ < 3
01127         typedef ss_typename_type_k mfcstl_ns_qual_std(iterator_traits)<I2> traits_t;
01128 
01129         return is_valid_source_range_(first, last, traits_t::iterator_category());
01130 # elif defined(STLSOFT_COMPILER_IS_MWERKS)
01131         return is_valid_source_range_(first, last, stlsoft_iterator_query_category_ptr(I2, first));
01132 # elif defined(STLSOFT_COMPILER_IS_DMC)
01133         return true;
01134 # else 
01135         return is_valid_source_range_(first, last, stlsoft_iterator_query_category(I2, first));
01136 # endif 
01137     }
01138 
01139 #if 0
01140     template <ss_typename_param_k T2>
01141     static ms_bool_t is_valid_source_range_(T2* first, T2* last)
01142     {
01143         return first <= last;
01144     }
01145 #endif 
01146 
01147 #if 0
01148     template <ss_typename_param_k T2>
01149     static ms_bool_t is_valid_source_range_(T2 const* first, T2 const* last)
01150     {
01151         return first <= last;
01152     }
01153 #endif 
01155 
01158 private:
01159     CArray_adaptor_base(class_type const& rhs);
01160     class_type& operator =(class_type const& rhs);
01162 };
01163 
01164 #ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
01165 
01196 #endif 
01197 template<   ss_typename_param_k A
01198         ,   ss_typename_param_k T = CArray_traits<A>
01199         >
01200 class CArray_cadaptor
01201         : public A
01202         , public CArray_adaptor_base<A, CArray_cadaptor<A, T>, T>
01203 {
01206 private:
01207     typedef CArray_adaptor_base<A, CArray_cadaptor<A, T>, T>        parent_class_type;
01208 public:
01210     typedef ss_typename_type_k parent_class_type::array_type        array_type;
01212     typedef ss_typename_type_k parent_class_type::value_type        value_type;
01214     typedef ss_typename_type_k parent_class_type::allocator_type    allocator_type;
01216     typedef ss_typename_type_k parent_class_type::reference         reference;
01218     typedef ss_typename_type_k parent_class_type::const_reference   const_reference;
01220     typedef ss_typename_type_k parent_class_type::pointer           pointer;
01222     typedef ss_typename_type_k parent_class_type::const_pointer     const_pointer;
01224     typedef ss_typename_type_k parent_class_type::iterator          iterator;
01226     typedef ss_typename_type_k parent_class_type::const_iterator    const_iterator;
01228     typedef ss_typename_type_k parent_class_type::size_type         size_type;
01230     typedef ss_typename_type_k parent_class_type::difference_type   difference_type;
01232     typedef CArray_cadaptor<A, T>                                   class_type;
01234 
01237 private:
01238     friend class CArray_adaptor_base<A, CArray_cadaptor<A, T>, T>;
01239 
01240     array_type          &get_actual_array()
01241     {
01242         return *this;
01243     }
01244     array_type const    &get_actual_array() const
01245     {
01246         return *this;
01247     }
01249 
01252 public:
01258     ss_explicit_k CArray_cadaptor(allocator_type const& = allocator_type())
01259     {
01260         parent_class_type::resize(0);   
01261     }
01265     explicit CArray_cadaptor(size_type n)
01266     {
01267         parent_class_type::resize(n);
01268     }
01273     CArray_cadaptor(size_type n, value_type const& value)
01274     {
01275         parent_class_type::assign(n, value);
01276     }
01278     CArray_cadaptor(class_type const& rhs)
01279     {
01280         parent_class_type::assign(rhs.begin(), rhs.end());
01281     }
01283     CArray_cadaptor(array_type const& rhs)
01284     {
01285         parent_class_type::assign(rhs.GetData(), rhs.GetData() + rhs.GetSize());
01286     }
01288     template <ss_typename_param_k I2>
01289     CArray_cadaptor(I2 first, I2 last)
01290     {
01291         
01292         MFCSTL_ASSERT(parent_class_type::is_valid_source_range_(first, last));
01293 
01294         parent_class_type::assign(first, last);
01295     }
01296     ~CArray_cadaptor() stlsoft_throw_0()
01297     {
01298         STLSOFT_STATIC_ASSERT(sizeof(A) == sizeof(ss_typename_type_k T::array_type));
01299     }
01301 
01304 public:
01305     class_type& operator =(class_type const& rhs)
01306     {
01307 #ifdef MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT
01308         class_type t(rhs);
01309         t.swap(*this);
01310 #else 
01311         parent_class_type::assign(rhs.begin(), rhs.end());
01312 #endif 
01313 
01314         return *this;
01315     }
01317 
01320 public:
01321 #if defined(STLSOFT_COMPILER_IS_DMC)
01322     reference operator [](size_type index)
01323     {
01324         return parent_class_type::operator [](index);
01325     }
01326     const_reference operator [](size_type index) const
01327     {
01328         return parent_class_type::operator [](index);
01329     }
01330 #else 
01331     using parent_class_type::operator [];
01332 #endif 
01334 };
01335 
01336 
01337 #ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
01338 
01368 #endif 
01369 template<   ss_typename_param_k A
01370         ,   ss_typename_param_k T = CArray_traits<A>
01371         >
01372 class CArray_iadaptor
01373         : public CArray_adaptor_base<A, CArray_iadaptor<A, T>, T>
01374 {
01377 private:
01378     typedef CArray_adaptor_base<A, CArray_iadaptor<A, T>, T>        parent_class_type;
01379 public:
01381     typedef ss_typename_type_k parent_class_type::array_type        array_type;
01383     typedef ss_typename_type_k parent_class_type::value_type        value_type;
01385     typedef ss_typename_type_k parent_class_type::allocator_type    allocator_type;
01387     typedef ss_typename_type_k parent_class_type::reference         reference;
01389     typedef ss_typename_type_k parent_class_type::const_reference   const_reference;
01391     typedef ss_typename_type_k parent_class_type::pointer           pointer;
01393     typedef ss_typename_type_k parent_class_type::const_pointer     const_pointer;
01395     typedef ss_typename_type_k parent_class_type::iterator          iterator;
01397     typedef ss_typename_type_k parent_class_type::const_iterator    const_iterator;
01399     typedef ss_typename_type_k parent_class_type::size_type         size_type;
01401     typedef ss_typename_type_k parent_class_type::difference_type   difference_type;
01403     typedef CArray_iadaptor<A, T>                                   class_type;
01405 
01408 private:
01409     friend class CArray_adaptor_base<A, CArray_iadaptor<A, T>, T>;
01410 
01411     array_type          &get_actual_array()
01412     {
01413         MFCSTL_ASSERT(NULL != m_pArray);
01414         return *m_pArray;
01415     }
01416     array_type const    &get_actual_array() const
01417     {
01418         MFCSTL_ASSERT(NULL != m_pArray);
01419         return *m_pArray;
01420     }
01422 
01425 public:
01426     template <ss_typename_param_k A2>
01427     CArray_iadaptor(A2 &array)
01428          : m_pArray(&array)
01429     {
01430         STLSOFT_STATIC_ASSERT(sizeof(array_type) == sizeof(A2));
01431 #ifdef STLSOFT_META_HAS_IS_SAME_TYPE
01432         STLSOFT_STATIC_ASSERT((stlsoft::is_same_type<array_type, A2>::value));
01433 #else 
01434         ASSERT(0 == ::lstrcmpA(array.GetRuntimeClass()->m_lpszClassName, array_type().GetRuntimeClass()->m_lpszClassName));
01435 # ifdef _CPPRTTI
01436         ASSERT(0 == ::lstrcmpA(typeid(A2).name(), typeid(array_type).name()));
01437 # endif 
01438 #endif 
01439     }
01440     template <ss_typename_param_k A2>
01441     CArray_iadaptor(A2 *pArray)
01442          : m_pArray(pArray)
01443     {
01444         MFCSTL_MESSAGE_ASSERT("Cannot initialise a CArray_iadaptor with a NULL pointer", NULL != pArray);
01445 
01446         STLSOFT_STATIC_ASSERT(sizeof(array_type) == sizeof(A2));
01447 #ifdef STLSOFT_META_HAS_IS_SAME_TYPE
01448         STLSOFT_STATIC_ASSERT((stlsoft::is_same_type<array_type, A2>::value));
01449 #else 
01450         ASSERT(0 == ::lstrcmpA(pArray->GetRuntimeClass()->m_lpszClassName, array_type().GetRuntimeClass()->m_lpszClassName));
01451 # ifdef _CPPRTTI
01452         ASSERT(0 == ::lstrcmpA(typeid(A2).name(), typeid(array_type).name()));
01453 # endif 
01454 #endif 
01455     }
01457 
01460 private:
01461     array_type  *m_pArray;
01463 
01466 private:
01467     CArray_iadaptor(class_type const& rhs);            
01468     class_type& operator =(class_type const& rhs);  
01470 };
01471 
01472 
01473 
01474 
01475 
01476 template<   ss_typename_param_k A1
01477         ,   ss_typename_param_k A2
01478         ,   ss_typename_param_k I1
01479         ,   ss_typename_param_k I2
01480         ,   ss_typename_param_k T1
01481         ,   ss_typename_param_k T2
01482         >
01483 inline ms_bool_t operator ==(CArray_adaptor_base<A1, I1, T1> const& lhs, CArray_adaptor_base<A2, I2, T2> const& rhs)
01484 {
01485     return lhs.equal(rhs);
01486 }
01487 
01488 template<   ss_typename_param_k A1
01489         ,   ss_typename_param_k A2
01490         ,   ss_typename_param_k I1
01491         ,   ss_typename_param_k I2
01492         ,   ss_typename_param_k T1
01493         ,   ss_typename_param_k T2
01494         >
01495 inline ms_bool_t operator !=(CArray_adaptor_base<A1, I1, T1> const& lhs, CArray_adaptor_base<A2, I2, T2> const& rhs)
01496 {
01497     return !lhs.equal(rhs);
01498 }
01499 
01500 template<   ss_typename_param_k A1
01501         ,   ss_typename_param_k A2
01502         ,   ss_typename_param_k I1
01503         ,   ss_typename_param_k I2
01504         ,   ss_typename_param_k T1
01505         ,   ss_typename_param_k T2
01506         >
01507 inline ms_bool_t operator <(CArray_adaptor_base<A1, I1, T1> const& lhs, CArray_adaptor_base<A2, I2, T2> const& rhs)
01508 {
01509     return lhs.less_than(rhs);
01510 }
01511 
01512 template<   ss_typename_param_k A1
01513         ,   ss_typename_param_k A2
01514         ,   ss_typename_param_k I1
01515         ,   ss_typename_param_k I2
01516         ,   ss_typename_param_k T1
01517         ,   ss_typename_param_k T2
01518         >
01519 inline ms_bool_t operator <=(CArray_adaptor_base<A1, I1, T1> const& lhs, CArray_adaptor_base<A2, I2, T2> const& rhs)
01520 {
01521     return !lhs.greater_than(rhs);
01522 }
01523 
01524 template<   ss_typename_param_k A1
01525         ,   ss_typename_param_k A2
01526         ,   ss_typename_param_k I1
01527         ,   ss_typename_param_k I2
01528         ,   ss_typename_param_k T1
01529         ,   ss_typename_param_k T2
01530         >
01531 inline ms_bool_t operator >(CArray_adaptor_base<A1, I1, T1> const& lhs, CArray_adaptor_base<A2, I2, T2> const& rhs)
01532 {
01533     return lhs.greater_than(rhs);
01534 }
01535 
01536 template<   ss_typename_param_k A1
01537         ,   ss_typename_param_k A2
01538         ,   ss_typename_param_k I1
01539         ,   ss_typename_param_k I2
01540         ,   ss_typename_param_k T1
01541         ,   ss_typename_param_k T2
01542         >
01543 inline ms_bool_t operator >=(CArray_adaptor_base<A1, I1, T1> const& lhs, CArray_adaptor_base<A2, I2, T2> const& rhs)
01544 {
01545     return !lhs.less_than(rhs);
01546 }
01547 
01548 
01549 
01550 template<   ss_typename_param_k A
01551         ,   ss_typename_param_k I
01552         ,   ss_typename_param_k T
01553         >
01554 inline ms_bool_t operator ==(CArray_adaptor_base<A, I, T> const& lhs, A const& rhs)
01555 {
01556     return lhs.equal(rhs);
01557 }
01558 
01559 template<   ss_typename_param_k A
01560         ,   ss_typename_param_k I
01561         ,   ss_typename_param_k T
01562         >
01563 inline ms_bool_t operator !=(CArray_adaptor_base<A, I, T> const& lhs, A const& rhs)
01564 {
01565     return !lhs.equal(rhs);
01566 }
01567 
01568 template<   ss_typename_param_k A
01569         ,   ss_typename_param_k I
01570         ,   ss_typename_param_k T
01571         >
01572 inline ms_bool_t operator <(CArray_adaptor_base<A, I, T> const& lhs, A const& rhs)
01573 {
01574     return lhs.less_than(rhs);
01575 }
01576 
01577 template<   ss_typename_param_k A
01578         ,   ss_typename_param_k I
01579         ,   ss_typename_param_k T
01580         >
01581 inline ms_bool_t operator <=(CArray_adaptor_base<A, I, T> const& lhs, A const& rhs)
01582 {
01583     return !lhs.greater_than(rhs);
01584 }
01585 
01586 template<   ss_typename_param_k A
01587         ,   ss_typename_param_k I
01588         ,   ss_typename_param_k T
01589         >
01590 inline ms_bool_t operator >(CArray_adaptor_base<A, I, T> const& lhs, A const& rhs)
01591 {
01592     return lhs.greater_than(rhs);
01593 }
01594 
01595 template<   ss_typename_param_k A
01596         ,   ss_typename_param_k I
01597         ,   ss_typename_param_k T
01598         >
01599 inline ms_bool_t operator >=(CArray_adaptor_base<A, I, T> const& lhs, A const& rhs)
01600 {
01601     return !lhs.less_than(rhs);
01602 }
01603 
01604 
01605 
01606 
01607 template<   ss_typename_param_k A
01608         ,   ss_typename_param_k I
01609         ,   ss_typename_param_k T
01610         >
01611 inline ms_bool_t operator ==(A const& lhs, CArray_adaptor_base<A, I, T> const& rhs)
01612 {
01613     return rhs.equal(lhs);
01614 }
01615 
01616 template<   ss_typename_param_k A
01617         ,   ss_typename_param_k I
01618         ,   ss_typename_param_k T
01619         >
01620 inline ms_bool_t operator !=(A const& lhs, CArray_adaptor_base<A, I, T> const& rhs)
01621 {
01622     return !rhs.equal(lhs);
01623 }
01624 
01625 template<   ss_typename_param_k A
01626         ,   ss_typename_param_k I
01627         ,   ss_typename_param_k T
01628         >
01629 inline ms_bool_t operator <(A const& lhs, CArray_adaptor_base<A, I, T> const& rhs)
01630 {
01631     return !(rhs.greater_than(lhs) || rhs == lhs);
01632 }
01633 
01634 template<   ss_typename_param_k A
01635         ,   ss_typename_param_k I
01636         ,   ss_typename_param_k T
01637         >
01638 inline ms_bool_t operator <=(A const& lhs, CArray_adaptor_base<A, I, T> const& rhs)
01639 {
01640     return !rhs.less_than(lhs);
01641 }
01642 
01643 template<   ss_typename_param_k A
01644         ,   ss_typename_param_k I
01645         ,   ss_typename_param_k T
01646         >
01647 inline ms_bool_t operator >(A const& lhs, CArray_adaptor_base<A, I, T> const& rhs)
01648 {
01649     return !(rhs.less_than(lhs) || rhs == lhs);
01650 }
01651 
01652 template<   ss_typename_param_k A
01653         ,   ss_typename_param_k I
01654         ,   ss_typename_param_k T
01655         >
01656 inline ms_bool_t operator >=(A const& lhs, CArray_adaptor_base<A, I, T> const& rhs)
01657 {
01658     return !rhs.greater_than(lhs);
01659 }
01660 
01662 
01663 
01664 #ifdef STLSOFT_UNITTEST
01665 # include "./unittest/carray_adaptors_unittest_.h"
01666 #endif 
01667 
01668 
01669 
01670 #ifndef _MFCSTL_NO_NAMESPACE
01671 # if defined(_STLSOFT_NO_NAMESPACE) || \
01672      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
01673 } 
01674 # else
01675 } 
01676 } 
01677 # endif 
01678 #endif 
01679 
01680 
01681 
01682 #endif 
01683 
01684