// xmemory internal header (from <memory>) -*-c++-*-
// Copyright 2009-2017 IAR Systems AB.
#ifndef _XMEMORY_
#define _XMEMORY_

#ifndef _SYSTEM_BUILD
  #pragma system_include
#endif

#include <xmemory0>

namespace std {

// TEMPLATE FUNCTION get_temporary_buffer
template<class _Ty> inline
pair<_Ty *, ptrdiff_t>
get_temporary_buffer(ptrdiff_t _Count) _NOEXCEPT
{       // get raw temporary buffer of up to _Count elements
  _Ty *_Pbuf;

  if (_Count < 0)
    _Count = 0;
  else if (((size_t)(-1) / sizeof (_Ty) < _Count))
    __iar_Raise_bad_alloc();  // report no memory
  for (_Pbuf = 0; 0 < _Count; _Count /= 2)
    if ((_Pbuf = (_Ty *)operator new(
           (size_t)_Count * sizeof (_Ty), nothrow)) != 0)
      break;

  return pair<_Ty *, ptrdiff_t>(_Pbuf, _Count);
}

// TEMPLATE FUNCTION return_temporary_buffer
template<class _Ty> inline
void return_temporary_buffer(_Ty *_Pbuf)
{       // delete raw temporary buffer
  operator delete(_Pbuf);
}

#define _WRAP_ALLOC(al)       _Wrap_alloc<al>

// TEMPLATE FUNCTION uninitialized_copy_n
template<class _InIt,
         class _Diff,
         class _FwdIt> inline
_FwdIt _Uninitialized_copy_n(_InIt _First, _Diff _Count,
                             _FwdIt _Dest, input_iterator_tag)
{       // copy [_First, _First + _Count) to [_Dest, ...), input iterators
  _FwdIt _Next = _Dest;

  _TRY_BEGIN
    _Construct(std::addressof(*_Dest),
               *_First);   // 0 < _Count has been guaranteed
    while (0 < --_Count)
      _Construct(std::addressof(*++_Dest), *++_First);
  _CATCH_ALL
    for (; _Next != _Dest; ++_Next)
      _Destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END
  return ++_Dest;
}

template<class _InIt,
         class _Diff,
         class _FwdIt> inline
_FwdIt _Uninitialized_copy_n(_InIt _First, _Diff _Count,
                             _FwdIt _Dest, forward_iterator_tag)
{       // copy [_First, _First + _Count) to [_Dest, ...), forward iterators
  _FwdIt _Next = _Dest;

  _TRY_BEGIN
    for (; 0 < _Count; --_Count, (void)++_Dest, ++_First)
      _Construct(std::addressof(*_Dest), *_First);
  _CATCH_ALL
    for (; _Next != _Dest; ++_Next)
      _Destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END
  return _Dest;
}

template<class _InIt,
         class _Diff,
         class _FwdIt> inline
_FwdIt _Uninitialized_copy_n(_InIt _First, _Diff _Count,
                             _FwdIt _Dest, _Nonscalar_ptr_iterator_tag)
{       // copy [_First, _First + _Count) to [_Dest, ...), arbitrary iterators
  return _Uninitialized_copy_n(_First, _Count, _Dest, _Iter_cat(_First));
}

template<class _InIt,
         class _Diff,
         class _FwdIt> inline
_FwdIt _Uninitialized_copy_n(_InIt _First, _Diff _Count,
                             _FwdIt _Dest, _Scalar_ptr_iterator_tag)
{       // copy [_First, _First + _Count) to [_Dest, ...), pointers to scalars
  ::memmove(&*_Dest, &*_First, _Count * sizeof (*_First));
  return _Dest + _Count;
}

template<class _InIt,
         class _Diff,
         class _FwdIt> inline
_FwdIt _Uninitialized_copy_n(_InIt _First, _Diff _Count, _FwdIt _Dest)
{       // copy [_First, _First + _Count) to [_Dest, ...), unchecked
  return _Uninitialized_copy_n(_First, _Count, _Dest, _Ptr_cat(_First, _Dest));
}

#if _ITERATOR_DEBUG_LEVEL == 0
  template<class _InIt,
           class _Diff,
           class _FwdIt> inline
  _FwdIt uninitialized_copy_n(_InIt _First, _Diff _Count, _FwdIt _Dest)
  {       // copy [_First, _First + _Count) to [_Dest, ...)
    if (_Count <= 0)
      return _Dest;
    else
      return _Rechecked(_Dest,
                        _Uninitialized_copy_n(_Unchecked(_First), _Count,
                                              _Unchecked(_Dest)));
  }
#else /* _ITERATOR_DEBUG_LEVEL == 0 */
  template<class _InIt,
           class _Diff,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy_n2(_InIt _First, _Diff _Count,
                                _FwdIt _Dest, _Mutable_iterator_tag)
  {       // copy [_First, _First + _Count) to [_Dest, ...), arbitrary dest
    return _Uninitialized_copy_n(_First, _Count, _Dest);
  }

  template<class _InIt,
           class _Diff,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy_n2(_InIt _First, _Diff _Count,
                                _FwdIt _Dest, random_access_iterator_tag)
  {       // copy [_First, _First + _Count) to [_Dest, ...), random-access dest
    _FwdIt _Ans = _Dest + _Count;   // also checks range
    _Uninitialized_copy_n(_First, _Count,
                          _Unchecked(_Dest));
    return _Ans;
  }

  template<class _InIt,
           class _Diff,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy_n1(_InIt _First, _Diff _Count,
                                _FwdIt _Dest, input_iterator_tag)
  {       // copy [_First, _First + _Count) to [_Dest, ...), arbitrary input
    return _Uninitialized_copy_n2(_First, _Count, _Dest, _Iter_cat(_Dest));
  }

  template<class _InIt,
           class _Diff,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy_n1(_InIt _First, _Diff _Count,
                                _FwdIt _Dest, random_access_iterator_tag)
  {       // copy [_First, _First + _Count) to [_Dest, ...), random-access input
    _InIt _Last = _First + _Count;  // also checks range
    _Last = _Last;  // to quiet diagnostics
    return _Uninitialized_copy_n2(_Unchecked(_First), _Count,
                                  _Dest, _Iter_cat(_Dest));
  }

  template<class _InIt,
           class _Diff,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy_n(_InIt _First, _Diff _Count,
                               _FwdIt _Dest, true_type)
  {       // copy [_First, _First + _Count) to [_Dest, ...), checked dest
    return _Uninitialized_copy_n1(_First, _Count, _Dest, _Iter_cat(_First));
  }

  template<class _InIt,
           class _Diff,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy_n(_InIt _First, _Diff _Count,
                               _FwdIt _Dest, false_type)
  {       // copy [_First, _First + _Count) to [_Dest, ...), unchecked dest
    return _Uninitialized_copy_n1(_First, _Count, _Dest, _Iter_cat(_First));
  }

  template<class _InIt,
           class _Diff,
           class _FwdIt> inline
  _FwdIt uninitialized_copy_n(_InIt _First, _Diff _Count, _FwdIt _Dest)
  {       // copy [_First, _First + _Count) to [_Dest, ...)
    if (_Count <= 0)
      return _Dest;
    else
    {	// validate _First/_Dest and copy
      _DEBUG_POINTER(_First);
      _DEBUG_POINTER(_Dest);
      return _Uninitialized_copy_n(_First, _Count, _Dest, _Is_checked(_Dest));
    }
  }

  template<class _InTy,
           size_t _InSize,
           class _Diff,
           class _FwdIt> inline
  _FwdIt uninitialized_copy_n(_InTy (&_First)[_InSize], _Diff _Count,
                              _FwdIt _Dest)
  {       // copy [_First, _First + _Count) to [_Dest, ...), array input
    return uninitialized_copy_n(_Array_iterator<_InTy, _InSize>(_First),
                                _Count, _Dest);
  }

  template<class _InIt,
           class _Diff,
           class _OutTy,
           size_t _OutSize> inline
  _OutTy *uninitialized_copy_n(_InIt _First, _Diff _Count,
                               _OutTy (&_Dest)[_OutSize])
  {       // copy [_First, _First + _Count) to [_Dest, ...), array dest
    return _Unchecked(uninitialized_copy_n(_First,
                                           _Count, _Array_iterator<_OutTy,
                                           _OutSize>(_Dest)));
  }

  template<class _InTy,
           size_t _InSize,
           class _Diff,
           class _OutTy,
           size_t _OutSize> inline
  _OutTy *uninitialized_copy_n(_InTy (&_First)[_InSize], _Diff _Count,
                               _OutTy (&_Dest)[_OutSize])
  {       // copy [_First, _First + _Count) to [_Dest, ...), array input/dest
    return _Unchecked(
              uninitialized_copy_n(_Array_iterator<_InTy, _InSize>(_First),
                                   _Count, _Array_iterator<_OutTy,
                                   _OutSize>(_Dest)));
  }
#endif /* _ITERATOR_DEBUG_LEVEL == 0 */

// TEMPLATE FUNCTION uninitialized_copy
template<class _InIt,
         class _FwdIt> inline
_FwdIt _Uninitialized_copy0(_InIt _First, _InIt _Last,
                            _FwdIt _Dest, _Nonscalar_ptr_iterator_tag)
{       // copy [_First, _Last) to raw [_Dest, ...), arbitrary iterators
  _FwdIt _Next = _Dest;

  _TRY_BEGIN
    for (; _First != _Last; ++_Dest, (void)++_First)
      _Construct(std::addressof(*_Dest), *_First);
  _CATCH_ALL
    for (; _Next != _Dest; ++_Next)
      _Destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END
  return _Dest;
}

template<class _InIt,
         class _FwdIt> inline
_FwdIt _Uninitialized_copy0(_InIt _First, _InIt _Last,
                            _FwdIt _Dest, _Scalar_ptr_iterator_tag)
{       // copy [_First, _Last) to raw [_Dest, ...), pointers to scalars
  ptrdiff_t _Count = _Last - _First;
  ::memmove(&*_Dest, &*_First,
                _Count * sizeof (*_First));
  return _Dest + _Count;
}

template<class _InIt,
         class _FwdIt> inline
_FwdIt _Uninitialized_copy0(_InIt _First, _InIt _Last, _FwdIt _Dest)
{       // copy [_First, _Last) to raw [_Dest, ...)
  return _Uninitialized_copy0(_First, _Last, _Dest, _Ptr_cat(_First, _Dest));
}

#if _ITERATOR_DEBUG_LEVEL == 0
  template<class _InIt,
           class _FwdIt> inline
  _FwdIt uninitialized_copy(_InIt _First, _InIt _Last, _FwdIt _Dest)
  {       // copy [_First, _Last) to raw [_Dest, ...)
    return _Rechecked(_Dest, _Uninitialized_copy0(_Unchecked(_First),
                                                  _Unchecked(_Last),
                                                  _Unchecked(_Dest)));
  }
#else /* _ITERATOR_DEBUG_LEVEL == 0 */
  template<class _InIt,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy0(_InIt _First, _InIt _Last,
                              _FwdIt _Dest, input_iterator_tag,
                              forward_iterator_tag)
  {       // copy [_First, _Last) to raw [_Dest, ...), arbitrary iterators
    return _Uninitialized_copy0(_First, _Last, _Dest);
  }

  template<class _InIt,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy0(_InIt _First, _InIt _Last,
                              _FwdIt _Dest, random_access_iterator_tag,
                              random_access_iterator_tag)
  {       // copy [_First, _Last) to raw [_Dest, ...), random-access iterators
    _FwdIt _Ans = _Dest + (_Last - _First); // also checks range
    _Uninitialized_copy0(_First, _Last, _Unchecked(_Dest));
    return _Ans;
  }

  template<class _InIt,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy0(_InIt _First, _InIt _Last,
                              _FwdIt _Dest, true_type)
  {       // copy [_First, _Last) to raw [_Dest, ...), checked dest
    return _Uninitialized_copy0(_First, _Last,
                                _Dest, _Iter_cat(_First), _Iter_cat(_Dest));
  }

  template<class _InIt,
           class _FwdIt> inline
  _FwdIt _Uninitialized_copy0(_InIt _First, _InIt _Last,
                              _FwdIt _Dest, false_type)
  {       // copy [_First, _Last) to raw [_Dest, ...), unchecked dest
    return _Uninitialized_copy0(_First, _Last,
                                _Dest, _Iter_cat(_First), _Iter_cat(_Dest));
  }

  template<class _InIt,
           class _FwdIt> inline
  _FwdIt uninitialized_copy(_InIt _First, _InIt _Last, _FwdIt _Dest)
  {       // copy [_First, _Last) to raw [_Dest, ...)
    _DEBUG_RANGE_PTR(_First, _Last, _Dest);
    return _Uninitialized_copy0(_Unchecked(_First), _Unchecked(_Last),
                                _Dest, _Is_checked(_Dest));
  }

  template<class _InIt,
           class _OutTy,
           size_t _OutSize> inline
  _OutTy *uninitialized_copy(_InIt _First, _InIt _Last,
                             _OutTy (&_Dest)[_OutSize])
  {       // copy [_First, _Last) to raw [_Dest, ...)
    return _Unchecked(uninitialized_copy(_First, _Last,
                                     _Array_iterator<_OutTy, _OutSize>(_Dest)));
  }
#endif /* _ITERATOR_DEBUG_LEVEL == 0 */

// TEMPLATE FUNCTION _Uninitialized_copy WITH ALLOCATOR
template<class _InIt,
         class _FwdIt,
         class _Alloc> inline
_FwdIt _Uninit_copy(_InIt _First, _InIt _Last, _FwdIt _Dest,
                    _WRAP_ALLOC(_Alloc)& _Al, _Nonscalar_ptr_iterator_tag)
{       // copy [_First, _Last) to raw _Dest, using _Al, arbitrary type
  _DEBUG_RANGE_PTR(_First, _Last, _Dest);
  _FwdIt _Next = _Dest;

  _TRY_BEGIN
    for (; _First != _Last; ++_Dest, (void)++_First)
      _Al.construct(std::addressof(*_Dest), *_First);
  _CATCH_ALL
    for (; _Next != _Dest; ++_Next)
      _Al.destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END
  return _Dest;
}

template<class _InIt,
         class _FwdIt,
         class _Alloc> inline
_FwdIt _Uninit_copy(_InIt _First, _InIt _Last, _FwdIt _Dest,
                    _WRAP_ALLOC(_Alloc)& _Al, _Scalar_ptr_iterator_tag)
{       // copy [_First, _Last) to raw _Dest, using _Al, scalar type
  return _Uninit_copy(_First, _Last, _Dest,
                      _Al, _Nonscalar_ptr_iterator_tag());
}

template<class _Ty1,
         class _Ty2> inline
_Ty2 *_Uninit_copy(_Ty1 *_First, _Ty1 *_Last, _Ty2 *_Dest,
                   _WRAP_ALLOC(allocator<_Ty2> )&, _Scalar_ptr_iterator_tag)
{       // copy [_First, _Last) to raw _Dest, scalar type
  _DEBUG_RANGE_PTR(_First, _Last, _Dest);
  size_t _Count = (size_t)(_Last - _First);
  return (_Ty2 *)::memmove(&*_Dest, &*_First,
                           _Count * sizeof (*_First)) + _Count;
                                                    // NB: non-overlapping move
}

template<class _InIt,
         class _FwdIt,
         class _Alloc> inline
_FwdIt _Uninit_copy(_InIt _First, _InIt _Last, _FwdIt _Dest, _Alloc& _Al)
{       // copy [_First, _Last) to raw _Dest, using _Al
  return _Uninit_copy(_First, _Last, _Dest, _Al, _Ptr_cat(_First, _Dest));
}

template<class _InIt,
         class _FwdIt,
         class _Alloc> inline
_FwdIt _Uninitialized_copy(_InIt _First, _InIt _Last, _FwdIt _Dest, _Alloc& _Al)
{       // copy [_First, _Last) to raw _Dest, using _Al
  return _Rechecked(_Dest, _Uninit_copy(_Unchecked(_First), _Unchecked(_Last),
                                        _Unchecked(_Dest), _Al));
}

// TEMPLATE FUNCTION _Uninitialized_move WITH ALLOCATOR
template<class _InIt,
         class _FwdIt,
         class _Alloc,
         class _Valty> inline
_FwdIt _Uninit_move(_InIt _First, _InIt _Last, _FwdIt _Dest,
                    _WRAP_ALLOC(_Alloc)& _Al, _Valty *,
                    _Nonscalar_ptr_iterator_tag)
{       // move [_First, _Last) to raw _Dest, using _Al, arbitrary type
  _DEBUG_RANGE_PTR(_First, _Last, _Dest);
  _FwdIt _Next = _Dest;

  _TRY_BEGIN
    for (; _First != _Last; ++_Dest, (void)++_First)
      _Al.construct(std::addressof(*_Dest), (_Valty &&)*_First);
  _CATCH_ALL
    for (; _Next != _Dest; ++_Next)
      _Al.destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END
  return _Dest;
}

template<class _InIt,
         class _FwdIt,
         class _Alloc,
         class _Valty> inline
_FwdIt _Uninit_move(_InIt _First, _InIt _Last, _FwdIt _Dest,
                    _WRAP_ALLOC(_Alloc)& _Al, _Valty *,
                    _Scalar_ptr_iterator_tag)
{       // move [_First, _Last) to raw _Dest, using _Al, scalar type
  return _Uninit_move(_First, _Last, _Dest,
                      _Al, (_Valty *)0, _Nonscalar_ptr_iterator_tag());
}

template<class _Ty1,
         class _Ty2,
         class _Valty> inline
_Ty2 *_Uninit_move(_Ty1 *_First, _Ty1 *_Last, _Ty2 *_Dest,
                   _WRAP_ALLOC(allocator<_Ty2> )&, _Valty *,
                   _Scalar_ptr_iterator_tag)
{       // move [_First, _Last) to raw _Dest, scalar type
  _DEBUG_RANGE_PTR(_First, _Last, _Dest);
  size_t _Count = (size_t)(_Last - _First);
  return (_Ty2 *)::memmove(&*_Dest, &*_First,
                           _Count * sizeof (*_First)) + _Count;
                                                   // NB: non-overlapping move
}

template<class _InIt,
         class _FwdIt,
         class _Alloc> inline
_FwdIt _Uninit_move(_InIt _First, _InIt _Last, _FwdIt _Dest, _Alloc& _Al)
{       // move [_First, _Last) to raw _Dest, using _Al
  return _Uninit_move(_First, _Last, _Dest, _Al,
                      _Val_type(_First), _Ptr_cat(_First, _Dest));
}

template<class _InIt,
         class _FwdIt,
         class _Alloc> inline
_FwdIt _Uninitialized_move(_InIt _First, _InIt _Last, _FwdIt _Dest, _Alloc& _Al)
{       // move [_First, _Last) to raw _Dest, using _Al
  return _Rechecked(_Dest, _Uninit_move(_Unchecked(_First), _Unchecked(_Last),
                                        _Unchecked(_Dest), _Al));
}

// TEMPLATE FUNCTION uninitialized_fill
template<class _FwdIt,
         class _Tval> inline
void _Uninit_fill(_FwdIt _First, _FwdIt _Last, const _Tval& _Val,
                  _Nonscalar_ptr_iterator_tag)
{       // copy _Val throughout raw [_First, _Last), arbitrary type
  _DEBUG_RANGE(_First, _Last);
  _FwdIt _Next = _First;

  _TRY_BEGIN
    for (; _First != _Last; ++_First)
      _Construct(std::addressof(*_First), _Val);
  _CATCH_ALL
    for (; _Next != _First; ++_Next)
      _Destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END
}

template<class _Ty,
         class _Tval> inline
void _Uninit_fill(_Ty *_First, _Ty *_Last, const _Tval& _Val,
                  _Scalar_ptr_iterator_tag)
{       // copy _Val throughout raw [_First, _Last), scalar type
  std::fill(_First, _Last, _Val);
}

template<class _FwdIt,
         class _Tval> inline
void uninitialized_fill(_FwdIt _First, _FwdIt _Last, const _Tval& _Val)
{       // copy _Val throughout raw [_First, _Last)
  _Uninit_fill(_First, _Last, _Val, _Ptr_cat(_First, _First));
}

// TEMPLATE FUNCTION uninitialized_fill_n
template<class _FwdIt,
         class _Diff,
         class _Tval> inline
_FwdIt _Uninit_fill_n(_FwdIt _First, _Diff _Count, const _Tval& _Val,
                      _Nonscalar_ptr_iterator_tag)
{       // copy _Count *_Val to raw _First, arbitrary type
  #if _ITERATOR_DEBUG_LEVEL == 2
    // if (_Count < 0)
    //   _DEBUG_ERROR("negative count in uninitialized fill");
  #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

  _FwdIt _Next = _First;

  _TRY_BEGIN
    for (; 0 < _Count; --_Count, (void)++_First)
      _Construct(std::addressof(*_First), _Val);
  _CATCH_ALL
    for (; _Next != _First; ++_Next)
      _Destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END

  return _First;
}

template<class _Ty,
         class _Diff,
         class _Tval> inline
_Ty *_Uninit_fill_n(_Ty *_First, _Diff _Count, const _Tval& _Val,
                    _Scalar_ptr_iterator_tag)
{       // copy _Count *_Val to raw _First, scalar type
  return _Fill_n(_First, _Count, _Val);
}

template<class _FwdIt,
         class _Diff,
         class _Tval> inline
_FwdIt uninitialized_fill_n(_FwdIt _First, _Diff _Count, const _Tval& _Val)
{       // copy _Count *_Val to raw _First
  return _Uninit_fill_n(_First, _Count, _Val, _Ptr_cat(_First, _First));
}

// TEMPLATE FUNCTION _Uninitialized_fill_n WITH ALLOCATOR
template<class _FwdIt,
         class _Diff,
         class _Tval,
         class _Alloc,
         class _Valty> inline
void _Uninit_fill_n(_FwdIt _First, _Diff _Count,
                    const _Tval *_Pval, _WRAP_ALLOC(_Alloc)& _Al,
                    _Valty *, _Nonscalar_ptr_iterator_tag)
{       // copy _Count * *_Pval to raw _First, using _Al, arbitrary type
  #if _ITERATOR_DEBUG_LEVEL == 2
    // if (_Count < 0)
    //   _DEBUG_ERROR("negative count in uninitialized fill");
  #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

  _FwdIt _Next = _First;

  _TRY_BEGIN
    for (; 0 < _Count; --_Count, (void)++_First)
      _Al.construct(std::addressof(*_First), *_Pval);
  _CATCH_ALL
    for (; _Next != _First; ++_Next)
      _Al.destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END
}

template<class _FwdIt,
         class _Diff,
         class _Tval,
         class _Alloc,
         class _Valty> inline
void _Uninit_fill_n(_FwdIt _First, _Diff _Count,
                    const _Tval *_Pval, _WRAP_ALLOC(_Alloc)& _Al,
                    _Valty *, _Scalar_ptr_iterator_tag)
{       // copy _Count * *_Pval to raw _First, using _Al, arbitrary type
  _Uninit_fill_n(_First, _Count,
                 _Pval, _Al, (_Valty *)0, _Nonscalar_ptr_iterator_tag());
}

template<class _Ty,
         class _Diff,
         class _Tval,
         class _Valty> inline
void _Uninit_fill_n(_Ty *_First, _Diff _Count,
                    const _Tval *_Pval, _WRAP_ALLOC(allocator<_Ty> )&,
                    _Valty *, _Scalar_ptr_iterator_tag)
{       // copy _Count * *_Pval to raw _First, using _Al, scalar type
  _Fill_n(_First, _Count, *_Pval);
}

template<class _FwdIt,
         class _Diff,
         class _Tval,
         class _Alloc> inline
void _Uninitialized_fill_n(_FwdIt _First, _Diff _Count,
                           const _Tval *_Pval, _Alloc& _Al)
{       // copy _Count * *_Pval to raw _First, using _Al
  _Uninit_fill_n(_First, _Count, _Pval, _Al,
                 _Val_type(_First), _Ptr_cat(_First, _First));
}

// TEMPLATE FUNCTION _Uninitialized_default_fill_n WITH ALLOCATOR
template<class _FwdIt,
         class _Diff,
         class _Alloc,
         class _Valty> inline
void _Uninit_def_fill_n(_FwdIt _First, _Diff _Count,
                        _WRAP_ALLOC(_Alloc)& _Al, _Valty *,
                        _Nonscalar_ptr_iterator_tag)
{       // copy _Count * _Valty() to raw _First, using _Al, arbitrary type
  #if _ITERATOR_DEBUG_LEVEL == 2
    // if (_Count < 0)
    //   _DEBUG_ERROR("negative count in uninitialized fill");
  #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

  _FwdIt _Next = _First;

  _TRY_BEGIN
    for (; 0 < _Count; --_Count, (void)++_First)
      _Al.construct(std::addressof(*_First));
  _CATCH_ALL
    for (; _Next != _First; ++_Next)
      _Al.destroy(std::addressof(*_Next));
    _RERAISE;
  _CATCH_END
}

template<class _FwdIt,
         class _Diff,
         class _Alloc,
         class _Valty> inline
void _Uninit_def_fill_n(_FwdIt _First, _Diff _Count,
                        _WRAP_ALLOC(_Alloc)& _Al, _Valty *,
                        _Scalar_ptr_iterator_tag)
{       // copy _Count * _Valty() to raw _First, using _Al, arbitrary type
  _Uninit_def_fill_n(_First, _Count,
                     _Al, (_Valty *)0, _Nonscalar_ptr_iterator_tag());
}

template<class _Ty,
         class _Diff,
         class _Valty> inline
void _Uninit_def_fill_n(_Ty *_First, _Diff _Count,
                        _WRAP_ALLOC(allocator<_Ty> )&, _Valty *,
                        _Scalar_ptr_iterator_tag)
{       // copy _Count * _Valty() to raw _First, using _Al, scalar type
  _Fill_n(_First, _Count, (_Valty)0);
}

template<class _FwdIt,
         class _Diff,
         class _Alloc> inline
void _Uninitialized_default_fill_n(_FwdIt _First, _Diff _Count,
                                   _Alloc& _Al)
{       // copy _Count * _Val_type(_First)() to raw _First, using _Al
  _Uninit_def_fill_n(_First, _Count, _Al,
                     _Val_type(_First), _Ptr_cat(_First, _First));
}

// TEMPLATE CLASS raw_storage_iterator
template<class _OutIt,
         class _Ty>
class raw_storage_iterator
  : public _Outit
{       // wrap stores to raw buffer as output iterator
public:
  explicit raw_storage_iterator(_OutIt _First)
    : _Next(_First)
  {       // construct with iterator
  }

  raw_storage_iterator<_OutIt, _Ty>& operator*()
  {       // pretend to return designated value
    return *this;
  }

  raw_storage_iterator<_OutIt, _Ty>& operator=(const _Ty& _Val)
  {       // construct value designated by stored iterator
    _Construct(std::addressof(*_Next), _Val);
    return *this;
  }

  raw_storage_iterator<_OutIt, _Ty>& operator++()
  {       // preincrement
    ++_Next;
    return *this;
  }

  raw_storage_iterator<_OutIt, _Ty> operator++(int)
  {       // postincrement
    raw_storage_iterator<_OutIt, _Ty> _Ans = *this;
    ++_Next;
    return _Ans;
  }

  _OutIt base() const
  {	// return the stored iterator
    return _Next;
  }

private:
  _OutIt _Next;   // the stored iterator
};

// TEMPLATE CLASS _Temp_iterator
template<class _Ty>
class _Temp_iterator
  : public _Outit
{       // wrap stores to temporary buffer as output iterator
public:
  typedef _Ty *_Pty;

  _Temp_iterator(ptrdiff_t _Count = 0)
  {       // construct from desired temporary buffer size
    _Buf._Begin = 0;
    _Buf._Current = 0;
    _Buf._Hiwater = 0;
    _Buf._Size = _Count;    // memorize size for lazy allocation
    _Pbuf = &_Buf;
  }

  _Temp_iterator(const _Temp_iterator<_Ty>& _Right)
  {       // construct from _Right (share active buffer)
    _Buf._Begin = 0;        // clear stored buffer, for safe destruction
    _Buf._Current = 0;
    _Buf._Hiwater = 0;
    _Buf._Size = 0;
    *this = _Right;
  }

  ~_Temp_iterator() _NOEXCEPT
  {       // destroy the object
    if (_Buf._Begin != 0)
    {       // destroy any constructed elements in buffer
      for (_Pty _Next = _Buf._Begin;
           _Next != _Buf._Hiwater; ++_Next)
        _Destroy(_Next);
      std::return_temporary_buffer(_Buf._Begin);
    }
  }

  _Temp_iterator<_Ty>& operator=(const _Temp_iterator<_Ty>& _Right)
  {       // assign _Right (share active buffer)
    _Pbuf = _Right._Pbuf;
    return *this;
  }

  _Temp_iterator<_Ty>& operator=(const _Ty& _Val)
  {       // assign or construct value into active buffer, and increment
    if (_Pbuf->_Current < _Pbuf->_Hiwater)
      *_Pbuf->_Current++ = _Val;      // below high water mark, assign
    else
    {       // above high water mark, construct
      _Pty _Ptr = _Pbuf->_Current;
      _Construct(_Ptr, _Val);
      _Pbuf->_Hiwater = ++_Pbuf->_Current;
    }
    return *this;
  }

  _Temp_iterator<_Ty>& operator=(_Ty&& _Val)
  {       // move or construct value into active buffer, and increment
    if (_Pbuf->_Current < _Pbuf->_Hiwater)
      *_Pbuf->_Current++ = std::forward<_Ty>(_Val);    // below high water mark, move
    else
    {       // above high water mark, construct
      _Pty _Ptr = _Pbuf->_Current;
      _Construct(_Ptr, std::forward<_Ty>(_Val));
      _Pbuf->_Hiwater = ++_Pbuf->_Current;
    }
    return *this;
  }

  _Temp_iterator<_Ty>& operator*()
  {       // pretend to return designated value
    return *this;
  }

  _Temp_iterator<_Ty>& operator++()
  {       // pretend to preincrement
    return *this;
  }

  _Temp_iterator<_Ty>& operator++(int)
  {       // pretend to postincrement
    return *this;
  }

  _Temp_iterator<_Ty>& _Init()
  {       // set pointer at beginning of buffer
    _Pbuf->_Current = _Pbuf->_Begin;
    return *this;
  }

  _Pty _First() const
  {       // return pointer to beginning of buffer
    return _Pbuf->_Begin;
  }

  _Pty _Last() const
  {       // return pointer past end of buffer contents
    return _Pbuf->_Current;
  }

  ptrdiff_t _Maxlen()
  {       // return size of buffer
    if (_Pbuf->_Begin == 0 && 0 < _Pbuf->_Size)
    {       // allocate buffer on first size query
      pair<_Pty, ptrdiff_t> _Pair =
        std::get_temporary_buffer<_Ty>(_Pbuf->_Size);

      _Pbuf->_Begin = _Pair.first;
      _Pbuf->_Current = _Pair.first;
      _Pbuf->_Hiwater = _Pair.first;
      _Pbuf->_Size = _Pair.second;
    }
    return _Pbuf->_Size;
  }

private:
  struct _Bufpar
  {       // control information for a temporary buffer
    _Pty _Begin;    // pointer to beginning of buffer
    _Pty _Current;  // pointer to next available element
    _Pty _Hiwater;  // pointer to first unconstructed element
    ptrdiff_t _Size;        // length of buffer
  };
  _Bufpar _Buf;   // buffer control stored in iterator
  _Bufpar *_Pbuf; // pointer to active buffer control
};

// TEMPLATE CLASS auto_ptr
template<class _Ty>
class auto_ptr;

template<class _Ty>
struct auto_ptr_ref
{       // proxy reference for auto_ptr copying
  explicit auto_ptr_ref(_Ty *_Right)
    : _Ref(_Right)
  {       // construct from generic pointer to auto_ptr ptr
  }

  _Ty *_Ref;      // generic pointer to auto_ptr ptr
};

template<class _Ty>
class auto_ptr
{       // wrap an object pointer to ensure destruction
public:
  typedef auto_ptr<_Ty> _Myt;
  typedef _Ty element_type;

  explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
    : _Myptr(_Ptr)
  {       // construct from object pointer
  }

  auto_ptr(_Myt& _Right) _THROW0()
  : _Myptr(_Right.release())
  {       // construct by assuming pointer from _Right auto_ptr
  }

  auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
  {       // construct by assuming pointer from _Right auto_ptr_ref
    _Ty *_Ptr = _Right._Ref;
    _Right._Ref = 0;        // release old
    _Myptr = _Ptr;  // reset this
  }

  template<class _Other>
  operator auto_ptr<_Other>() _THROW0()
  {       // convert to compatible auto_ptr
    return auto_ptr<_Other>(*this);
  }

  template<class _Other>
  operator auto_ptr_ref<_Other>() _THROW0()
  {       // convert to compatible auto_ptr_ref
    _Other *_Cvtptr = _Myptr;       // test implicit conversion
    auto_ptr_ref<_Other> _Ans(_Cvtptr);
    _Myptr = 0;     // pass ownership to auto_ptr_ref
    return _Ans;
  }

  template<class _Other>
  _Myt& operator=(auto_ptr<_Other>& _Right) _THROW0()
  {       // assign compatible _Right (assume pointer)
    reset(_Right.release());
    return *this;
  }

  template<class _Other>
  auto_ptr(auto_ptr<_Other>& _Right) _THROW0()
    : _Myptr(_Right.release())
  {       // construct by assuming pointer from _Right
  }

  _Myt& operator=(_Myt& _Right) _THROW0()
  {       // assign compatible _Right (assume pointer)
    reset(_Right.release());
    return *this;
  }

  _Myt& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()
  {       // assign compatible _Right._Ref (assume pointer)
    _Ty *_Ptr = _Right._Ref;
    _Right._Ref = 0;        // release old
    reset(_Ptr);    // set new
    return *this;
  }

  ~auto_ptr() _NOEXCEPT
  {       // destroy the object
    delete _Myptr;
  }

  _Ty& operator*() const _THROW0()
  {       // return designated value
    #if _ITERATOR_DEBUG_LEVEL == 2
      if (_Myptr == 0)
        _DEBUG_ERROR("auto_ptr not dereferencable");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    return *get();
  }

  _Ty *operator->() const _THROW0()
  {       // return pointer to class object
    #if _ITERATOR_DEBUG_LEVEL == 2
      if (_Myptr == 0)
        _DEBUG_ERROR("auto_ptr not dereferencable");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

    return get();
  }

  _Ty *get() const _THROW0()
  {       // return wrapped pointer
    return _Myptr;
  }

  _Ty *release() _THROW0()
  {       // return wrapped pointer and give up ownership
    _Ty *_Tmp = _Myptr;
    _Myptr = 0;
    return _Tmp;
  }

  void reset(_Ty *_Ptr = 0)
  {       // destroy designated object and store new pointer
    if (_Ptr != _Myptr)
      delete _Myptr;
    _Myptr = _Ptr;
  }

private:
  _Ty *_Myptr;    // the wrapped object pointer
};

} /* namespace std */

#endif /* _XMEMORY_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0576 */
