You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
916 lines
24 KiB
916 lines
24 KiB
// -*- C++ -*-
|
|
/***************************************************************************
|
|
*
|
|
* memory - declarations for the Standard Library memory implementation
|
|
*
|
|
* $Id: memory 173524 2012-02-07 16:46:27Z ismith $
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* Copyright (c) 1994
|
|
* Hewlett-Packard Company
|
|
*
|
|
* Permission to use, copy, modify, distribute and sell this software
|
|
* and its documentation for any purpose is hereby granted without fee,
|
|
* provided that the above copyright notice appear in all copies and
|
|
* that both that copyright notice and this permission notice appear
|
|
* in supporting documentation. Hewlett-Packard Company makes no
|
|
* representations about the suitability of this software for any
|
|
* purpose. It is provided "as is" without express or implied warranty.
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* Copyright (c) 1994-2001 Rogue Wave Software, Inc. All Rights Reserved.
|
|
*
|
|
* This computer software is owned by Rogue Wave Software, Inc. and is
|
|
* protected by U.S. copyright laws and other laws and by international
|
|
* treaties. This computer software is furnished by Rogue Wave Software,
|
|
* Inc. pursuant to a written license agreement and may be used, copied,
|
|
* transmitted, and stored only in accordance with the terms of such
|
|
* license and with the inclusion of the above copyright notice. This
|
|
* computer software or any other copies thereof may not be provided or
|
|
* otherwise made available to any other person.
|
|
*
|
|
* U.S. Government Restricted Rights. This computer software is provided
|
|
* with Restricted Rights. Use, duplication, or disclosure by the
|
|
* Government is subject to restrictions as set forth in subparagraph (c)
|
|
* (1) (ii) of The Rights in Technical Data and Computer Software clause
|
|
* at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
|
|
* Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19,
|
|
* as applicable. Manufacturer is Rogue Wave Software, Inc., 5500
|
|
* Flatiron Parkway, Boulder, Colorado 80301 USA.
|
|
*
|
|
**************************************************************************/
|
|
|
|
#ifndef _RWSTD_MEMORY_INCLUDED
|
|
#define _RWSTD_MEMORY_INCLUDED
|
|
|
|
#include <new>
|
|
#include <utility>
|
|
|
|
#include <rw/_iterbase.h>
|
|
#include <rw/_mutex.h>
|
|
#include <rw/_defs.h>
|
|
|
|
|
|
_RWSTD_NAMESPACE_BEGIN (__rw)
|
|
|
|
// [de]allocate storage (in bytes)
|
|
_RWSTD_EXPORT void* __rw_allocate (_RWSTD_C::size_t, int = 0);
|
|
_RWSTD_EXPORT void __rw_deallocate (void*, _RWSTD_C::size_t, int = 0);
|
|
|
|
// this function returns a suggested new capacity for a container needing
|
|
// more room; see stddefs.h for an explanation of these macro parameters;
|
|
// the _Container template parameter allows more specialized overloads
|
|
// for customization
|
|
template <class _Container>
|
|
inline _RWSTD_C::size_t __rw_new_capacity (_RWSTD_C::size_t __size, const _Container*)
|
|
{
|
|
_RWSTD_C::size_t __cap = _RWSTD_STATIC_CAST (_RWSTD_C::size_t,
|
|
_RWSTD_INCREASE_CAPACITY(__size)
|
|
/*__size * _RWSTD_NEW_CAPACITY_RATIO*/);
|
|
return (__size += _RWSTD_MINIMUM_NEW_CAPACITY) > __cap ? __size : __cap;
|
|
}
|
|
|
|
|
|
template <class _TypeT>
|
|
inline void __rw_destroy (_TypeT &__ref)
|
|
{
|
|
__ref.~_TypeT ();
|
|
}
|
|
|
|
|
|
template <class _TypeT, class _TypeU>
|
|
inline void __rw_construct (_TypeT* __p, const _TypeU& __val)
|
|
{
|
|
new (__p) _TypeT (__val);
|
|
}
|
|
|
|
|
|
template <class _ForwardIterator>
|
|
void __rw_destroy (_ForwardIterator __first, _ForwardIterator __last)
|
|
{
|
|
for (; __first != __last; ++__first)
|
|
__rw_destroy (*__first);
|
|
}
|
|
|
|
|
|
#ifndef _RWSTD_NO_PTR_VALUE_TEMPLATE_OVERLOAD
|
|
|
|
// for compilers that don't optimize "empty" loops
|
|
template <class _TypeT>
|
|
inline void __rw_destroy (_TypeT**, _TypeT**)
|
|
{ }
|
|
|
|
#endif // _RWSTD_NO_PTR_VALUE_TEMPLATE_OVERLOAD
|
|
|
|
|
|
_RWSTD_NAMESPACE_END // __rw
|
|
|
|
|
|
_RWSTD_NAMESPACE_BEGIN (std)
|
|
|
|
|
|
template <class _TypeT> class
|
|
allocator;
|
|
|
|
|
|
_RWSTD_SPECIALIZED_CLASS
|
|
class allocator<void>
|
|
{
|
|
public:
|
|
typedef void* pointer;
|
|
typedef const void* const_pointer;
|
|
typedef void value_type;
|
|
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
|
|
template <class _TypeU>
|
|
struct rebind {
|
|
typedef allocator<_TypeU> other;
|
|
};
|
|
|
|
#endif /* _RWSTD_ALLOCATOR */
|
|
|
|
};
|
|
|
|
|
|
template <class _TypeT>
|
|
class allocator
|
|
{
|
|
public:
|
|
typedef _RWSTD_C::size_t size_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef _TypeT value_type;
|
|
typedef value_type* pointer;
|
|
typedef const value_type* const_pointer;
|
|
typedef value_type& reference;
|
|
typedef const value_type& const_reference;
|
|
|
|
allocator () _THROWS (()) { }
|
|
|
|
allocator (const allocator &__rhs) _THROWS (()) {
|
|
// working around an HP aCC warning 431
|
|
_RWSTD_UNUSED (__rhs);
|
|
}
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
|
|
template <class _TypeU>
|
|
struct rebind {
|
|
typedef allocator<_TypeU> other;
|
|
};
|
|
|
|
template <class _TypeU>
|
|
allocator (const allocator<_TypeU>&) _THROWS (()) { }
|
|
|
|
template <class _TypeU>
|
|
allocator&
|
|
operator= (const allocator<_TypeU>&) _THROWS (()) {
|
|
return *this;
|
|
}
|
|
|
|
#endif // _RWSTD_ALLOCATOR
|
|
|
|
|
|
pointer address (reference __x) const {
|
|
return &__x;
|
|
}
|
|
|
|
const_pointer address (const_reference __x) const {
|
|
return &__x;
|
|
}
|
|
|
|
pointer allocate (size_type __n, allocator<void>::const_pointer = 0) {
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
return _RWSTD_STATIC_CAST (pointer,
|
|
_RW::__rw_allocate (__n * sizeof (value_type)));
|
|
#else
|
|
return _RWSTD_STATIC_CAST (pointer, _RW::__rw_allocate (__n));
|
|
#endif // _RWSTD_ALLOCATOR
|
|
}
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
void deallocate (pointer __p, size_type __n)
|
|
#else
|
|
void deallocate (void* __p, size_type __n)
|
|
#endif // _RWSTD_ALLOCATOR
|
|
{
|
|
_RW::__rw_deallocate (__p, __n);
|
|
}
|
|
|
|
// 20.4.1.1, p11 - the largest N for which allocate (N) might succeed
|
|
size_type max_size () const _THROWS (()) {
|
|
return size_type (~0) / sizeof (value_type) ?
|
|
size_type (size_type (~0) / sizeof (value_type)) : size_type (1);
|
|
}
|
|
|
|
void construct (pointer __p, const_reference __val) {
|
|
_RW::__rw_construct (__p, __val);
|
|
}
|
|
|
|
void destroy (pointer __p) {
|
|
_RWSTD_ASSERT (0 != __p);
|
|
_RW::__rw_destroy (*__p);
|
|
}
|
|
};
|
|
|
|
|
|
#if !defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) \
|
|
&& !defined (_RWSTD_NO_EXT_CONST_ALLOCATOR)
|
|
|
|
// extension: allocates/constructs/destroys const elements
|
|
|
|
template <class _TypeT>
|
|
class allocator<const _TypeT>
|
|
{
|
|
public:
|
|
typedef _RWSTD_C::size_t size_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef const _TypeT value_type;
|
|
typedef const value_type* pointer;
|
|
typedef const value_type* const_pointer;
|
|
typedef const value_type& reference;
|
|
typedef const value_type& const_reference;
|
|
|
|
allocator () _THROWS (()) { }
|
|
|
|
allocator (const allocator &__rhs) _THROWS (()) {
|
|
// working around an HP aCC warning 431
|
|
_RWSTD_UNUSED (__rhs);
|
|
}
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
|
|
template <class _TypeU>
|
|
struct rebind {
|
|
typedef allocator<_TypeU> other;
|
|
};
|
|
|
|
template <class _TypeU>
|
|
allocator (const allocator<_TypeU>&) _THROWS (()) { }
|
|
|
|
template <class _TypeU>
|
|
allocator& operator= (const allocator<_TypeU>&) _THROWS (()) {
|
|
return *this;
|
|
}
|
|
|
|
#endif // _RWSTD_ALLOCATOR
|
|
|
|
const_pointer address (const_reference __x) const {
|
|
return &__x;
|
|
}
|
|
|
|
const_pointer
|
|
allocate (size_type __n, allocator<void>::const_pointer = 0) {
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
return _RWSTD_STATIC_CAST (const_pointer,
|
|
_RW::__rw_allocate (__n * sizeof (value_type)));
|
|
#else
|
|
return _RWSTD_STATIC_CAST (const_pointer, _RW::__rw_allocate (__n));
|
|
#endif // _RWSTD_ALLOCATOR
|
|
|
|
}
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
void deallocate (const_pointer __p, size_type __n /* elements */)
|
|
#else
|
|
void deallocate (const void* __p, size_type __n /* bytes */)
|
|
#endif // _RWSTD_ALLOCATOR
|
|
{
|
|
_RW::__rw_deallocate (_RWSTD_CONST_CAST (_TypeT*, __p), __n);
|
|
}
|
|
|
|
// 20.4.1.1, p11 - the largest N for which allocate (N) might succeed
|
|
size_type max_size () const _THROWS (()) {
|
|
return ~size_type (0) / sizeof (value_type) ?
|
|
size_type (size_type (~0) / sizeof (value_type)) : size_type (1);
|
|
}
|
|
|
|
void construct (const_pointer __p, const_reference __val) {
|
|
_RW::__rw_construct (_RWSTD_CONST_CAST (_TypeT*, __p), __val);
|
|
}
|
|
|
|
void destroy (const_pointer __p) {
|
|
_RWSTD_ASSERT (0 != __p);
|
|
_RW::__rw_destroy (_RWSTD_CONST_CAST (_TypeT&, *__p));
|
|
}
|
|
};
|
|
|
|
#endif // !_RWSTD_NO_CLASS_PARTIAL_SPEC && !_RWSTD_NO_EXT_CONST_ALLOCATOR)
|
|
|
|
|
|
// allocator_interface provides all types and typed functions. Memory
|
|
// allocated as raw bytes using the class provided by the Allocator
|
|
// template parameter. allocator_interface casts appropriately.
|
|
//
|
|
// Multiple allocator_interface objects can attach to a single
|
|
// allocator, thus allowing one allocator to allocate all storage
|
|
// for a container, regardless of how many types are involved.
|
|
//
|
|
// The only real restriction is that pointer and reference are
|
|
// hard coded as _TypeT* and _TypeT&. Partial specialization would
|
|
// get around this.
|
|
//
|
|
#ifndef _RWSTD_ALLOCATOR
|
|
|
|
template <class _Allocator, class _TypeT>
|
|
class allocator_interface
|
|
{
|
|
public:
|
|
typedef _Allocator allocator_type;
|
|
typedef _TypeT value_type;
|
|
typedef value_type* pointer;
|
|
typedef const value_type* const_pointer;
|
|
typedef value_type& reference;
|
|
typedef const value_type& const_reference;
|
|
typedef _TYPENAME allocator_type::size_type size_type;
|
|
typedef _TYPENAME allocator_type::difference_type difference_type;
|
|
|
|
protected:
|
|
allocator_type _C_alloc;
|
|
|
|
public:
|
|
allocator_interface() _THROWS (()) { }
|
|
|
|
allocator_interface (const allocator_type &__alloc) _THROWS (())
|
|
: _C_alloc (__alloc) { }
|
|
|
|
operator allocator_type& () {
|
|
return _C_alloc;
|
|
}
|
|
|
|
pointer address (reference __x) {
|
|
return &__x;
|
|
}
|
|
|
|
size_type max_size () const {
|
|
return _C_alloc.max_size () / sizeof (value_type);
|
|
}
|
|
|
|
pointer allocate (size_type __n, const void* __p = 0) {
|
|
//using c-style cast to perform reinterpret-cast & const-cast in 1 step
|
|
return (pointer)_C_alloc.allocate (__n * sizeof (value_type),
|
|
(pointer) __p );
|
|
}
|
|
|
|
void deallocate (pointer __p, size_type __n) {
|
|
_C_alloc.deallocate (__p, __n);
|
|
}
|
|
|
|
void construct (pointer __p, const_reference __val) const {
|
|
_RW::__rw_construct(__p, __val);
|
|
}
|
|
|
|
void destroy (pointer __p) const {
|
|
_RWSTD_ASSERT (0 != __p);
|
|
_RW::__rw_destroy (*__p);
|
|
}
|
|
};
|
|
|
|
|
|
_RWSTD_SPECIALIZED_CLASS
|
|
class allocator_interface<allocator<void>, void>
|
|
{
|
|
public:
|
|
typedef allocator<void> allocator_type;
|
|
typedef void* pointer;
|
|
typedef const void* const_pointer;
|
|
typedef void value_type;
|
|
|
|
protected:
|
|
allocator_type _C_alloc;
|
|
|
|
public:
|
|
allocator_interface () _THROWS (()) { }
|
|
|
|
allocator_interface (const allocator<void>& __rhs) _THROWS (())
|
|
: _C_alloc (__rhs) { }
|
|
|
|
};
|
|
|
|
|
|
template <class _TypeT, class _TypeU, class _TypeV, class _TypeW>
|
|
inline bool
|
|
operator== (const allocator_interface<_TypeT, _TypeU>&,
|
|
const allocator_interface<_TypeV, _TypeW>&) _THROWS (())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
#endif // _RWSTD_ALLOCATOR
|
|
|
|
|
|
template <class _TypeT, class _TypeU>
|
|
inline bool
|
|
operator== (const allocator<_TypeT>&, const allocator<_TypeU>&) _THROWS (())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
#ifndef _RWSTD_NO_NAMESPACE
|
|
|
|
template <class _TypeT, class _TypeU>
|
|
inline bool
|
|
operator!= (const allocator<_TypeT>& __x,
|
|
const allocator<_TypeU>& __y) _THROWS (())
|
|
{
|
|
return !(__x == __y);
|
|
}
|
|
|
|
#endif // _RWSTD_NO_NAMESPACE
|
|
|
|
|
|
// 20.4.2
|
|
template <class _OutputIterator, class _TypeT>
|
|
class raw_storage_iterator
|
|
: public iterator<output_iterator_tag, void, void, void, void>
|
|
{
|
|
_OutputIterator _C_iter;
|
|
public:
|
|
|
|
// for completeness and genericity
|
|
typedef _OutputIterator iterator_type;
|
|
|
|
// 20.4.2, p2
|
|
_EXPLICIT raw_storage_iterator (iterator_type __x) : _C_iter (__x) { }
|
|
|
|
// 20.4.2, p3
|
|
raw_storage_iterator& operator* () {
|
|
return *this;
|
|
}
|
|
|
|
// 20.4.2, p4
|
|
raw_storage_iterator& operator= (const _TypeT& __rhs) {
|
|
::new (&(*_C_iter)) _TypeT (__rhs);
|
|
return *this;
|
|
}
|
|
|
|
// 20.4.2, p6
|
|
raw_storage_iterator& operator++ () {
|
|
++_C_iter;
|
|
return *this;
|
|
}
|
|
|
|
// 20.4.2, p7
|
|
raw_storage_iterator operator++ (int) {
|
|
raw_storage_iterator __tmp = *this;
|
|
++*this;
|
|
return __tmp;
|
|
}
|
|
};
|
|
|
|
|
|
_RWSTD_NAMESPACE_END // std
|
|
|
|
|
|
_RWSTD_NAMESPACE_BEGIN (__rw)
|
|
|
|
// __rw_indestructible specializations should be objects with static
|
|
// storage duration that must "survive" all other static objects and that
|
|
// do not need to be destroyed; this is a POD
|
|
template <class _TypeT>
|
|
class __rw_indestructible
|
|
{
|
|
union _C_data_t {
|
|
char _C_data; // data to back _TypeT up with
|
|
long double _C_padding; // make sure data is suitably aligned
|
|
};
|
|
|
|
enum { _C_n = 1 + sizeof (_TypeT) / sizeof (_C_data_t) };
|
|
|
|
_C_data_t _C_data [_C_n]; // raw storage for an object of _TypeT
|
|
|
|
public:
|
|
typedef _TypeT value_type;
|
|
typedef value_type& reference;
|
|
typedef const value_type& const_reference;
|
|
typedef value_type* pointer;
|
|
typedef const value_type* const_pointer;
|
|
|
|
// no ctor to allow static POD initialization (3.6.2, p1)
|
|
|
|
// allow this to be used as a an obejct of another type
|
|
operator reference () {
|
|
return _RWSTD_REINTERPRET_CAST (reference, *_C_data);
|
|
}
|
|
|
|
operator const_reference () const {
|
|
return _RWSTD_REINTERPRET_CAST (const_reference, *_C_data);
|
|
}
|
|
|
|
// calls a conversion operator above
|
|
pointer operator& () {
|
|
// deprecated C-style cast used to make SunPro 5.0/T9 happy
|
|
// return &_RWSTD_STATIC_CAST (reference, *this);
|
|
|
|
return &(reference)*this;
|
|
}
|
|
|
|
// calls a conversion operator above
|
|
const_pointer operator& () const {
|
|
// deprecated C-style cast used to make SunPro 5.0/T9 happy
|
|
// return &_RWSTD_STATIC_CAST (const_reference, *this);
|
|
|
|
return &(const_reference)*this;
|
|
}
|
|
};
|
|
|
|
|
|
#ifdef _INLINE_WITH_STATICS
|
|
|
|
_INLINE_WITH_STATICS _RWSTD_EXPORT char* __rw_get_static_buf ()
|
|
{
|
|
typedef char _CharBuf [_RWSTD_TMPBUF_SIZE + 1];
|
|
|
|
// use `indestructible' to guarantee proper buffer alignment
|
|
static __rw_indestructible<_CharBuf> __buffer;
|
|
|
|
return _RWSTD_STATIC_CAST (char*, __buffer);
|
|
}
|
|
|
|
|
|
// [de]allocates a previously allocated temporary buffer
|
|
// the constant _RWSTD_TMPBUF_SIZE controls the size of a static buffer
|
|
// if request for area larger than _RWSTD_TMPBUF_SIZE comes in,
|
|
// space is allocated dynamically, otherwise the static buffer is used
|
|
// return value meaningful only if __n != 0
|
|
_INLINE_WITH_STATICS _RWSTD_EXPORT _STD::pair<void*, _RWSTD_C::size_t>
|
|
__rw_reallocate_temp_buffer (void *__p, _RWSTD_C::size_t __size)
|
|
{
|
|
// implicit initialization used to prevent a g++ 2.95.2 warning on Tru64
|
|
// sorry: semantics of inline function static data are wrong (you'll wind
|
|
// up with multiple copies)
|
|
|
|
static unsigned long __busy /* = 0 */; // > 0 when buffer in use
|
|
|
|
unsigned long __cntr = _RWSTD_ATOMIC_PREINCREMENT (__busy, false);
|
|
|
|
static char *__buffer = __rw_get_static_buf ();
|
|
|
|
if (__p == (void*)__buffer) {
|
|
__p = 0;
|
|
__size = 0;
|
|
|
|
// returning buffer, decrement usage counter
|
|
_RWSTD_ATOMIC_PREDECREMENT (__busy, false);
|
|
}
|
|
else
|
|
::operator delete (__p);
|
|
|
|
if (__size == 0) {
|
|
// buffer not used, decrement usage counter
|
|
_RWSTD_ATOMIC_PREDECREMENT (__busy, false);
|
|
}
|
|
else if (__size > _RWSTD_TMPBUF_SIZE || __cntr > 1) {
|
|
_TRY {
|
|
__p = ::operator new (__size);
|
|
}
|
|
_CATCH (...) {
|
|
__p = 0;
|
|
__size = 0;
|
|
}
|
|
|
|
// buffer not used, decrement usage counter
|
|
_RWSTD_ATOMIC_PREDECREMENT (__busy, false);
|
|
}
|
|
else {
|
|
__p = __buffer;
|
|
|
|
// buffer used, usage counter stays non-zero
|
|
}
|
|
|
|
return _STD::pair<void*, _RWSTD_C::size_t>(__p, __size);
|
|
}
|
|
|
|
#else // if !defined (_INLINE_WITH_STATICS)
|
|
|
|
_STD::pair<void*, _RWSTD_C::size_t> _RWSTD_EXPORT
|
|
__rw_reallocate_temp_buffer (void*, _RWSTD_C::size_t);
|
|
|
|
#endif // _INLINE_WITH_STATICS
|
|
|
|
_RWSTD_NAMESPACE_END // __rw
|
|
|
|
|
|
_RWSTD_NAMESPACE_BEGIN (std)
|
|
|
|
|
|
// 20.4.3 only specifies a get_temporary_buffer<>() that takes a ptrdiff_t.
|
|
// We overload on all types so that signed integral types other than ptrdiff_t
|
|
// can be used. This is important in getting algorithms to compile with
|
|
// user-defined iterators (not derived from iterator<...>) whose difference
|
|
// type is something other than ptrdiff_t.
|
|
|
|
// having this overload is important in some cases for compilers that
|
|
// do not support partial class specialization (and where as a consequence
|
|
// iterator_traits<> isn't available)
|
|
template <class _TypeT, class _Distance>
|
|
inline pair<_TypeT*, _Distance> get_temporary_buffer (_Distance __n, _TypeT*)
|
|
{
|
|
pair<void*, size_t> __pair =
|
|
_RW::__rw_reallocate_temp_buffer (0, __n * sizeof (_TypeT));
|
|
|
|
return make_pair (_RWSTD_STATIC_CAST (_TypeT*, __pair.first),
|
|
_Distance (__pair.second / sizeof (_TypeT)));
|
|
}
|
|
|
|
|
|
#ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
|
|
|
|
// 20.4.3, p1
|
|
template <class _TypeT>
|
|
inline pair<_TypeT*, ptrdiff_t> get_temporary_buffer (ptrdiff_t __n)
|
|
{
|
|
return get_temporary_buffer (__n, (_TypeT*)0);
|
|
}
|
|
|
|
#endif // _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
|
|
|
|
|
|
// 20.4.3, p3
|
|
template <class _TypeT>
|
|
inline void return_temporary_buffer (_TypeT *__p)
|
|
{
|
|
_RW::__rw_reallocate_temp_buffer (__p, 0);
|
|
}
|
|
|
|
|
|
// 20.4.4.1
|
|
template <class _InputIterator, class _ForwardIterator>
|
|
inline
|
|
_ForwardIterator uninitialized_copy (_InputIterator __first,
|
|
_InputIterator __last,
|
|
_ForwardIterator __res)
|
|
{
|
|
_ForwardIterator __start = __res;
|
|
|
|
_TRY {
|
|
for (; __first != __last; ++__first, ++__res)
|
|
_RW::__rw_construct (&*__res, *__first);
|
|
}
|
|
_CATCH (...) {
|
|
_RW::__rw_destroy (__start, __res);
|
|
_RETHROW;
|
|
}
|
|
|
|
return __res;
|
|
}
|
|
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
|
|
// extension
|
|
template <class _InputIterator, class _ForwardIterator, class _Allocator>
|
|
inline
|
|
_ForwardIterator uninitialized_copy (_InputIterator __first,
|
|
_InputIterator __last,
|
|
_ForwardIterator __res,
|
|
_Allocator& __alloc)
|
|
{
|
|
_ForwardIterator __start = __res;
|
|
|
|
_TRY {
|
|
for (; __first != __last; ++__first, ++__res)
|
|
__alloc.construct (&*__res, *__first);
|
|
}
|
|
_CATCH (...) {
|
|
for (; __start != __res; ++__start)
|
|
__alloc.destroy (&*__start);
|
|
_RETHROW;
|
|
}
|
|
|
|
return __res;
|
|
}
|
|
|
|
#endif // _RWSTD_ALLOCATOR
|
|
|
|
|
|
// 20.4.4.2
|
|
template <class _ForwardIterator, class _TypeT>
|
|
inline
|
|
void uninitialized_fill (_ForwardIterator __first, _ForwardIterator __last,
|
|
const _TypeT& __x)
|
|
{
|
|
_ForwardIterator __start = __first;
|
|
|
|
_TRY {
|
|
for (; __first != __last; ++__first)
|
|
_RW::__rw_construct (&*__first, __x);
|
|
}
|
|
_CATCH (...) {
|
|
_RW::__rw_destroy (__start, __first);
|
|
_RETHROW;
|
|
}
|
|
}
|
|
|
|
|
|
// 20.4.4.3
|
|
template <class _ForwardIterator, class _Size, class _TypeT>
|
|
inline
|
|
void uninitialized_fill_n (_ForwardIterator __first, _Size __n,
|
|
const _TypeT& __x)
|
|
{
|
|
_ForwardIterator __start = __first;
|
|
|
|
_TRY {
|
|
for (; __n; --__n, ++__first)
|
|
_RW::__rw_construct (&*__first, __x);
|
|
}
|
|
_CATCH (...) {
|
|
_RW::__rw_destroy (__start, __first);
|
|
_RETHROW;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef _RWSTD_ALLOCATOR
|
|
|
|
// extension
|
|
template <class _ForwardIter, class _Size, class _TypeT, class _Allocator>
|
|
inline
|
|
void uninitialized_fill_n (_ForwardIter __first, _Size __n,
|
|
const _TypeT& __x, _Allocator& __alloc)
|
|
{
|
|
_ForwardIter __start = __first;
|
|
|
|
_TRY {
|
|
for (; __n; --__n, ++__first)
|
|
__alloc.construct (&*__first, __x);
|
|
}
|
|
_CATCH (...) {
|
|
for (; __start != __first; ++__start)
|
|
__alloc.destroy (&*__start);
|
|
_RETHROW;
|
|
}
|
|
}
|
|
|
|
#else // if !defined (_RWSTD_ALLOCATOR)
|
|
|
|
// Specializations for non-standard allocators. When vector calls
|
|
// uninitialized_{copy,fill_n} with non-standard allocator, a temporary
|
|
// instance of allocator_interface is passed to these functions. Since
|
|
// C++ forbids temporaries to be passed as non-const references, we
|
|
// use these specializations to pass a const reference (and we can force
|
|
// allocator_interface members construct & destroy to be const).
|
|
|
|
template <class _InputIterator, class _ForwardIterator,
|
|
class _Allocator, class _TypeT>
|
|
inline _ForwardIterator
|
|
uninitialized_copy (_InputIterator __first,
|
|
_InputIterator __last,
|
|
_ForwardIterator __res,
|
|
const allocator_interface<_Allocator, _TypeT>& __alloc)
|
|
{
|
|
_ForwardIterator __start = __res;
|
|
|
|
_TRY {
|
|
for (; __first != __last; ++__first, ++__res)
|
|
__alloc.construct (&*__res, *__first);
|
|
}
|
|
_CATCH (...) {
|
|
for (; __start != __res; ++__start)
|
|
__alloc.destroy (&*__start);
|
|
_RETHROW;
|
|
}
|
|
|
|
return __res;
|
|
}
|
|
|
|
template <class _ForwardIter, class _Size,
|
|
class _TypeT, class _Allocator, class _TypeU>
|
|
inline void
|
|
uninitialized_fill_n (_ForwardIter __first, _Size __n,
|
|
const _TypeT& __x,
|
|
const allocator_interface<_Allocator, _TypeU>& __alloc)
|
|
{
|
|
_ForwardIter __start = __first;
|
|
|
|
_TRY {
|
|
for (; __n; --__n, ++__first)
|
|
__alloc.construct (&*__first, __x);
|
|
}
|
|
_CATCH (...) {
|
|
for (; __start != __first; ++__start)
|
|
__alloc.destroy (&*__start);
|
|
_RETHROW;
|
|
}
|
|
}
|
|
|
|
#endif // _RWSTD_ALLOCATOR
|
|
|
|
|
|
// 20.4.5 - Template class auto_ptr
|
|
|
|
template<class _TypeT>
|
|
class auto_ptr;
|
|
|
|
|
|
// 20.4.5, p2 (defined outside of auto_ptr<> according to the proposed
|
|
// resolution of lwg issue 127)
|
|
template <class _TypeT>
|
|
class auto_ptr_ref
|
|
{
|
|
public:
|
|
auto_ptr<_TypeT>& _C_ptr;
|
|
|
|
auto_ptr_ref (auto_ptr<_TypeT>& __rhs) : _C_ptr (__rhs) { }
|
|
};
|
|
|
|
|
|
template<class _TypeT>
|
|
class auto_ptr
|
|
{
|
|
public:
|
|
typedef _TypeT element_type;
|
|
|
|
_EXPLICIT auto_ptr (element_type* __p = 0) _THROWS (())
|
|
: _C_ptr (__p) { }
|
|
|
|
auto_ptr (auto_ptr& __rhs) _THROWS (())
|
|
: _C_ptr (__rhs.release ()) { }
|
|
|
|
auto_ptr& operator= (auto_ptr& __rhs) _THROWS (()) {
|
|
reset (__rhs.release ());
|
|
return *this;
|
|
}
|
|
|
|
// follows lwg issue 127
|
|
auto_ptr&
|
|
operator= (auto_ptr_ref<element_type> __rhs) _THROWS (()) {
|
|
reset (__rhs._C_ptr.release ());
|
|
return *this;
|
|
}
|
|
|
|
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
|
|
|
|
template <class _TypeU>
|
|
operator auto_ptr_ref<_TypeU>() _THROWS (()) {
|
|
return auto_ptr_ref<_TypeU>(*this);
|
|
}
|
|
|
|
template <class _TypeU>
|
|
operator auto_ptr<_TypeU>() _THROWS (()) {
|
|
return auto_ptr<_TypeU>(release ());
|
|
}
|
|
|
|
template <class _TypeU>
|
|
auto_ptr (auto_ptr<_TypeU>& __rhs) _THROWS (())
|
|
: _C_ptr (__rhs.release ()) { }
|
|
|
|
template <class _TypeU>
|
|
auto_ptr& operator= (auto_ptr<_TypeU>& __rhs) _THROWS (()) {
|
|
reset (__rhs.release ());
|
|
return *this;
|
|
}
|
|
|
|
#endif // _RWSTD_NO_MEMBER_TEMPLATES
|
|
|
|
|
|
~auto_ptr () _THROWS (()) {
|
|
delete _C_ptr;
|
|
}
|
|
|
|
element_type* get () const _THROWS (()) {
|
|
return _C_ptr;
|
|
}
|
|
|
|
element_type& operator* () const _THROWS (()) {
|
|
_RWSTD_ASSERT (0 != get ());
|
|
return *get ();
|
|
}
|
|
|
|
_RWSTD_OPERATOR_ARROW (
|
|
element_type* operator-> () const _THROWS (()))
|
|
|
|
element_type* release () _THROWS (()) {
|
|
element_type* __tmp = _C_ptr;
|
|
_C_ptr = 0;
|
|
return __tmp;
|
|
}
|
|
|
|
void reset (element_type* __p = 0) _THROWS (()) {
|
|
if (_C_ptr != __p) {
|
|
delete _C_ptr;
|
|
_C_ptr = __p;
|
|
}
|
|
}
|
|
|
|
auto_ptr (auto_ptr_ref<element_type> __r) _THROWS (())
|
|
: _C_ptr (__r._C_ptr.release ()) { }
|
|
|
|
private:
|
|
element_type* _C_ptr;
|
|
};
|
|
|
|
|
|
_RWSTD_NAMESPACE_END // std
|
|
|
|
|
|
#endif // _RWSTD_MEMORY_INCLUDED
|
|
|