stl_uninitialized.h

Go to the documentation of this file.
00001 // Raw memory manipulators -*- C++ -*-
00002 
00003 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
00004 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 3, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // Under Section 7 of GPL version 3, you are granted additional
00018 // permissions described in the GCC Runtime Library Exception, version
00019 // 3.1, as published by the Free Software Foundation.
00020 
00021 // You should have received a copy of the GNU General Public License and
00022 // a copy of the GCC Runtime Library Exception along with this program;
00023 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00024 // <http://www.gnu.org/licenses/>.
00025 
00026 /*
00027  *
00028  * Copyright (c) 1994
00029  * Hewlett-Packard Company
00030  *
00031  * Permission to use, copy, modify, distribute and sell this software
00032  * and its documentation for any purpose is hereby granted without fee,
00033  * provided that the above copyright notice appear in all copies and
00034  * that both that copyright notice and this permission notice appear
00035  * in supporting documentation.  Hewlett-Packard Company makes no
00036  * representations about the suitability of this software for any
00037  * purpose.  It is provided "as is" without express or implied warranty.
00038  *
00039  *
00040  * Copyright (c) 1996,1997
00041  * Silicon Graphics Computer Systems, Inc.
00042  *
00043  * Permission to use, copy, modify, distribute and sell this software
00044  * and its documentation for any purpose is hereby granted without fee,
00045  * provided that the above copyright notice appear in all copies and
00046  * that both that copyright notice and this permission notice appear
00047  * in supporting documentation.  Silicon Graphics makes no
00048  * representations about the suitability of this software for any
00049  * purpose.  It is provided "as is" without express or implied warranty.
00050  */
00051 
00052 /** @file stl_uninitialized.h
00053  *  This is an internal header file, included by other library headers.
00054  *  You should not attempt to use it directly.
00055  */
00056 
00057 #ifndef _STL_UNINITIALIZED_H
00058 #define _STL_UNINITIALIZED_H 1
00059 
00060 _GLIBCXX_BEGIN_NAMESPACE(std)
00061 
00062   template<bool>
00063     struct __uninitialized_copy
00064     {
00065       template<typename _InputIterator, typename _ForwardIterator>
00066         static _ForwardIterator
00067         uninitialized_copy(_InputIterator __first, _InputIterator __last,
00068                _ForwardIterator __result)
00069         {
00070       _ForwardIterator __cur = __result;
00071       __try
00072         {
00073           for (; __first != __last; ++__first, ++__cur)
00074         std::_Construct(&*__cur, *__first);
00075           return __cur;
00076         }
00077       __catch(...)
00078         {
00079           std::_Destroy(__result, __cur);
00080           __throw_exception_again;
00081         }
00082     }
00083     };
00084 
00085   template<>
00086     struct __uninitialized_copy<true>
00087     {
00088       template<typename _InputIterator, typename _ForwardIterator>
00089         static _ForwardIterator
00090         uninitialized_copy(_InputIterator __first, _InputIterator __last,
00091                _ForwardIterator __result)
00092         { return std::copy(__first, __last, __result); }
00093     };
00094 
00095   /**
00096    *  @brief Copies the range [first,last) into result.
00097    *  @param  first  An input iterator.
00098    *  @param  last   An input iterator.
00099    *  @param  result An output iterator.
00100    *  @return   result + (first - last)
00101    *
00102    *  Like copy(), but does not require an initialized output range.
00103   */
00104   template<typename _InputIterator, typename _ForwardIterator>
00105     inline _ForwardIterator
00106     uninitialized_copy(_InputIterator __first, _InputIterator __last,
00107                _ForwardIterator __result)
00108     {
00109       typedef typename iterator_traits<_InputIterator>::value_type
00110     _ValueType1;
00111       typedef typename iterator_traits<_ForwardIterator>::value_type
00112     _ValueType2;
00113 
00114       return std::__uninitialized_copy<(__is_pod(_ValueType1)
00115                     && __is_pod(_ValueType2))>::
00116     uninitialized_copy(__first, __last, __result);
00117     }
00118 
00119 
00120   template<bool>
00121     struct __uninitialized_fill
00122     {
00123       template<typename _ForwardIterator, typename _Tp>
00124         static void
00125         uninitialized_fill(_ForwardIterator __first,
00126                _ForwardIterator __last, const _Tp& __x)
00127         {
00128       _ForwardIterator __cur = __first;
00129       __try
00130         {
00131           for (; __cur != __last; ++__cur)
00132         std::_Construct(&*__cur, __x);
00133         }
00134       __catch(...)
00135         {
00136           std::_Destroy(__first, __cur);
00137           __throw_exception_again;
00138         }
00139     }
00140     };
00141 
00142   template<>
00143     struct __uninitialized_fill<true>
00144     {
00145       template<typename _ForwardIterator, typename _Tp>
00146         static void
00147         uninitialized_fill(_ForwardIterator __first,
00148                _ForwardIterator __last, const _Tp& __x)
00149         { std::fill(__first, __last, __x); }
00150     };
00151 
00152   /**
00153    *  @brief Copies the value x into the range [first,last).
00154    *  @param  first  An input iterator.
00155    *  @param  last   An input iterator.
00156    *  @param  x      The source value.
00157    *  @return   Nothing.
00158    *
00159    *  Like fill(), but does not require an initialized output range.
00160   */
00161   template<typename _ForwardIterator, typename _Tp>
00162     inline void
00163     uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last,
00164                const _Tp& __x)
00165     {
00166       typedef typename iterator_traits<_ForwardIterator>::value_type
00167     _ValueType;
00168 
00169       std::__uninitialized_fill<__is_pod(_ValueType)>::
00170 	uninitialized_fill(__first, __last, __x);
00171     }
00172 
00173 
00174   template<bool>
00175     struct __uninitialized_construct_range_dispatch
00176     {
00177       template<typename _ForwardIterator, typename _Tp>
00178         static void
00179         __ucr(_ForwardIterator __first, _ForwardIterator __last,
00180           _Tp& __value)
00181         {
00182       if(__first == __last)
00183         return;
00184 
00185       _ForwardIterator __cur = __first;
00186       __try
00187         {
00188           std::_Construct(&*__first, _GLIBCXX_MOVE(__value));
00189           _ForwardIterator __prev = __cur;
00190           ++__cur;
00191           for(; __cur != __last; ++__cur, ++__prev)
00192         std::_Construct(&*__cur, _GLIBCXX_MOVE(*__prev));
00193           __value = _GLIBCXX_MOVE(*__prev);
00194         }
00195       __catch(...)
00196         {
00197           std::_Destroy(__first, __cur);
00198           __throw_exception_again;
00199         }
00200     }
00201     };
00202 
00203   template<>
00204     struct __uninitialized_construct_range_dispatch<true>
00205     {
00206       template<typename _ForwardIterator, typename _Tp>
00207         static void
00208         __ucr(_ForwardIterator, _ForwardIterator, _Tp&) { }
00209     };
00210 
00211   // Constructs objects in the range [first, last).
00212   // Note that while these new objects will take valid values,
00213   // their exact value is not defined. In particular they may
00214   // be 'moved from'.
00215   //
00216   // While __value may altered during this algorithm, it will have
00217   // the same value when the algorithm finishes, unless one of the
00218   // constructions throws.
00219   //
00220   // Requirements: _ForwardIterator::value_type(_Tp&&) is valid.
00221   template<typename _ForwardIterator, typename _Tp>
00222     inline void
00223     __uninitialized_construct_range(_ForwardIterator __first,
00224                     _ForwardIterator __last,
00225                     _Tp& __value)
00226     {
00227       typedef typename std::iterator_traits<_ForwardIterator>::value_type
00228     _ValueType;
00229 
00230       std::__uninitialized_construct_range_dispatch<
00231         __has_trivial_constructor(_ValueType)>::
00232       __ucr(__first, __last, __value);
00233     }
00234 
00235 
00236   template<bool>
00237     struct __uninitialized_fill_n
00238     {
00239       template<typename _ForwardIterator, typename _Size, typename _Tp>
00240         static void
00241         uninitialized_fill_n(_ForwardIterator __first, _Size __n,
00242                  const _Tp& __x)
00243         {
00244       _ForwardIterator __cur = __first;
00245       __try
00246         {
00247           for (; __n > 0; --__n, ++__cur)
00248         std::_Construct(&*__cur, __x);
00249         }
00250       __catch(...)
00251         {
00252           std::_Destroy(__first, __cur);
00253           __throw_exception_again;
00254         }
00255     }
00256     };
00257 
00258   template<>
00259     struct __uninitialized_fill_n<true>
00260     {
00261       template<typename _ForwardIterator, typename _Size, typename _Tp>
00262         static void
00263         uninitialized_fill_n(_ForwardIterator __first, _Size __n,
00264                  const _Tp& __x)
00265         { std::fill_n(__first, __n, __x); }
00266     };
00267 
00268   /**
00269    *  @brief Copies the value x into the range [first,first+n).
00270    *  @param  first  An input iterator.
00271    *  @param  n      The number of copies to make.
00272    *  @param  x      The source value.
00273    *  @return   Nothing.
00274    *
00275    *  Like fill_n(), but does not require an initialized output range.
00276   */
00277   template<typename _ForwardIterator, typename _Size, typename _Tp>
00278     inline void
00279     uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
00280     {
00281       typedef typename iterator_traits<_ForwardIterator>::value_type
00282     _ValueType;
00283 
00284       std::__uninitialized_fill_n<__is_pod(_ValueType)>::
00285 	uninitialized_fill_n(__first, __n, __x);
00286     }
00287 
00288   // Extensions: versions of uninitialized_copy, uninitialized_fill,
00289   //  and uninitialized_fill_n that take an allocator parameter.
00290   //  We dispatch back to the standard versions when we're given the
00291   //  default allocator.  For nondefault allocators we do not use 
00292   //  any of the POD optimizations.
00293 
00294   template<typename _InputIterator, typename _ForwardIterator,
00295        typename _Allocator>
00296     _ForwardIterator
00297     __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
00298                _ForwardIterator __result, _Allocator& __alloc)
00299     {
00300       _ForwardIterator __cur = __result;
00301       __try
00302     {
00303       for (; __first != __last; ++__first, ++__cur)
00304         __alloc.construct(&*__cur, *__first);
00305       return __cur;
00306     }
00307       __catch(...)
00308     {
00309       std::_Destroy(__result, __cur, __alloc);
00310       __throw_exception_again;
00311     }
00312     }
00313 
00314   template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
00315     inline _ForwardIterator
00316     __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
00317                _ForwardIterator __result, allocator<_Tp>&)
00318     { return std::uninitialized_copy(__first, __last, __result); }
00319 
00320   template<typename _InputIterator, typename _ForwardIterator,
00321        typename _Allocator>
00322     inline _ForwardIterator
00323     __uninitialized_move_a(_InputIterator __first, _InputIterator __last,
00324                _ForwardIterator __result, _Allocator& __alloc)
00325     {
00326       return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
00327                      _GLIBCXX_MAKE_MOVE_ITERATOR(__last),
00328                      __result, __alloc);
00329     }
00330 
00331   template<typename _ForwardIterator, typename _Tp, typename _Allocator>
00332     void
00333     __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
00334                const _Tp& __x, _Allocator& __alloc)
00335     {
00336       _ForwardIterator __cur = __first;
00337       __try
00338     {
00339       for (; __cur != __last; ++__cur)
00340         __alloc.construct(&*__cur, __x);
00341     }
00342       __catch(...)
00343     {
00344       std::_Destroy(__first, __cur, __alloc);
00345       __throw_exception_again;
00346     }
00347     }
00348 
00349   template<typename _ForwardIterator, typename _Tp, typename _Tp2>
00350     inline void
00351     __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
00352                const _Tp& __x, allocator<_Tp2>&)
00353     { std::uninitialized_fill(__first, __last, __x); }
00354 
00355   template<typename _ForwardIterator, typename _Size, typename _Tp,
00356        typename _Allocator>
00357     void
00358     __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, 
00359                  const _Tp& __x, _Allocator& __alloc)
00360     {
00361       _ForwardIterator __cur = __first;
00362       __try
00363     {
00364       for (; __n > 0; --__n, ++__cur)
00365         __alloc.construct(&*__cur, __x);
00366     }
00367       __catch(...)
00368     {
00369       std::_Destroy(__first, __cur, __alloc);
00370       __throw_exception_again;
00371     }
00372     }
00373 
00374   template<typename _ForwardIterator, typename _Size, typename _Tp,
00375        typename _Tp2>
00376     inline void
00377     __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, 
00378                  const _Tp& __x, allocator<_Tp2>&)
00379     { std::uninitialized_fill_n(__first, __n, __x); }
00380 
00381 
00382   // Extensions: __uninitialized_copy_move, __uninitialized_move_copy,
00383   // __uninitialized_fill_move, __uninitialized_move_fill.
00384   // All of these algorithms take a user-supplied allocator, which is used
00385   // for construction and destruction.
00386 
00387   // __uninitialized_copy_move
00388   // Copies [first1, last1) into [result, result + (last1 - first1)), and
00389   //  move [first2, last2) into
00390   //  [result, result + (last1 - first1) + (last2 - first2)).
00391   template<typename _InputIterator1, typename _InputIterator2,
00392        typename _ForwardIterator, typename _Allocator>
00393     inline _ForwardIterator
00394     __uninitialized_copy_move(_InputIterator1 __first1,
00395                   _InputIterator1 __last1,
00396                   _InputIterator2 __first2,
00397                   _InputIterator2 __last2,
00398                   _ForwardIterator __result,
00399                   _Allocator& __alloc)
00400     {
00401       _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1,
00402                                __result,
00403                                __alloc);
00404       __try
00405     {
00406       return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc);
00407     }
00408       __catch(...)
00409     {
00410       std::_Destroy(__result, __mid, __alloc);
00411       __throw_exception_again;
00412     }
00413     }
00414 
00415   // __uninitialized_move_copy
00416   // Moves [first1, last1) into [result, result + (last1 - first1)), and
00417   //  copies [first2, last2) into
00418   //  [result, result + (last1 - first1) + (last2 - first2)).
00419   template<typename _InputIterator1, typename _InputIterator2,
00420        typename _ForwardIterator, typename _Allocator>
00421     inline _ForwardIterator
00422     __uninitialized_move_copy(_InputIterator1 __first1,
00423                   _InputIterator1 __last1,
00424                   _InputIterator2 __first2,
00425                   _InputIterator2 __last2,
00426                   _ForwardIterator __result,
00427                   _Allocator& __alloc)
00428     {
00429       _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1,
00430                                __result,
00431                                __alloc);
00432       __try
00433     {
00434       return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc);
00435     }
00436       __catch(...)
00437     {
00438       std::_Destroy(__result, __mid, __alloc);
00439       __throw_exception_again;
00440     }
00441     }
00442   
00443   // __uninitialized_fill_move
00444   // Fills [result, mid) with x, and moves [first, last) into
00445   //  [mid, mid + (last - first)).
00446   template<typename _ForwardIterator, typename _Tp, typename _InputIterator,
00447        typename _Allocator>
00448     inline _ForwardIterator
00449     __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid,
00450                   const _Tp& __x, _InputIterator __first,
00451                   _InputIterator __last, _Allocator& __alloc)
00452     {
00453       std::__uninitialized_fill_a(__result, __mid, __x, __alloc);
00454       __try
00455     {
00456       return std::__uninitialized_move_a(__first, __last, __mid, __alloc);
00457     }
00458       __catch(...)
00459     {
00460       std::_Destroy(__result, __mid, __alloc);
00461       __throw_exception_again;
00462     }
00463     }
00464 
00465   // __uninitialized_move_fill
00466   // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and
00467   //  fills [first2 + (last1 - first1), last2) with x.
00468   template<typename _InputIterator, typename _ForwardIterator, typename _Tp,
00469        typename _Allocator>
00470     inline void
00471     __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1,
00472                   _ForwardIterator __first2,
00473                   _ForwardIterator __last2, const _Tp& __x,
00474                   _Allocator& __alloc)
00475     {
00476       _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1,
00477                                 __first2,
00478                                 __alloc);
00479       __try
00480     {
00481       std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc);
00482     }
00483       __catch(...)
00484     {
00485       std::_Destroy(__first2, __mid2, __alloc);
00486       __throw_exception_again;
00487     }
00488     }
00489 
00490 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00491   template<typename _InputIterator, typename _Size,
00492        typename _ForwardIterator>
00493     _ForwardIterator
00494     __uninitialized_copy_n(_InputIterator __first, _Size __n,
00495                _ForwardIterator __result, input_iterator_tag)
00496     {
00497       _ForwardIterator __cur = __result;
00498       __try
00499     {
00500       for (; __n > 0; --__n, ++__first, ++__cur)
00501         ::new(static_cast<void*>(&*__cur)) typename
00502         iterator_traits<_ForwardIterator>::value_type(*__first);
00503       return __cur;
00504     }
00505       __catch(...)
00506     {
00507       std::_Destroy(__result, __cur);
00508       __throw_exception_again;
00509     }
00510     }
00511 
00512   template<typename _RandomAccessIterator, typename _Size,
00513        typename _ForwardIterator>
00514     inline _ForwardIterator
00515     __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n,
00516                _ForwardIterator __result,
00517                random_access_iterator_tag)
00518     { return std::uninitialized_copy(__first, __first + __n, __result); }
00519 
00520   /**
00521    *  @brief Copies the range [first,first+n) into result.
00522    *  @param  first  An input iterator.
00523    *  @param  n      The number of elements to copy.
00524    *  @param  result An output iterator.
00525    *  @return  result + n
00526    *
00527    *  Like copy_n(), but does not require an initialized output range.
00528   */
00529   template<typename _InputIterator, typename _Size, typename _ForwardIterator>
00530     inline _ForwardIterator
00531     uninitialized_copy_n(_InputIterator __first, _Size __n,
00532              _ForwardIterator __result)
00533     { return std::__uninitialized_copy_n(__first, __n, __result,
00534                      std::__iterator_category(__first)); }
00535 #endif
00536 
00537 _GLIBCXX_END_NAMESPACE
00538 
00539 #endif /* _STL_UNINITIALIZED_H */