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.
1009 lines
26 KiB
1009 lines
26 KiB
// list standard header
|
|
#pragma once
|
|
#ifndef _LIST_
|
|
#define _LIST_
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <stdexcept>
|
|
|
|
#pragma pack(push,8)
|
|
#pragma warning(push,3)
|
|
|
|
_STD_BEGIN
|
|
|
|
// TEMPLATE CLASS _List_nod
|
|
template<class _Ty,
|
|
class _Alloc>
|
|
class _List_nod
|
|
{ // base class for _List_ptr to hold allocator _Alnod
|
|
protected:
|
|
struct _Node;
|
|
friend struct _Node;
|
|
typedef typename _Alloc::_TEMPLATE_MEMBER
|
|
rebind<_Node>::other::pointer _Genptr;
|
|
|
|
struct _Node
|
|
{ // list node
|
|
_Node(_Genptr _Nextarg, _Genptr _Prevarg, const _Ty& _Myvalarg)
|
|
: _Next(_Nextarg), _Prev(_Prevarg), _Myval(_Myvalarg)
|
|
{ // construct a node with value
|
|
}
|
|
|
|
_Genptr _Next; // successor node, or first element if head
|
|
_Genptr _Prev; // predecessor node, or last element if head
|
|
_Ty _Myval; // the stored value, unused if head
|
|
};
|
|
|
|
_List_nod(_Alloc _Al)
|
|
: _Alnod(_Al)
|
|
{ // construct allocator from _Al
|
|
}
|
|
|
|
typename _Alloc::_TEMPLATE_MEMBER rebind<_Node>::other
|
|
_Alnod; // allocator object for nodes
|
|
};
|
|
|
|
// TEMPLATE CLASS _List_ptr
|
|
template<class _Ty,
|
|
class _Alloc>
|
|
class _List_ptr
|
|
: public _List_nod<_Ty, _Alloc>
|
|
{ // base class for _List_val to hold allocator _Alptr
|
|
protected:
|
|
typedef typename _List_nod<_Ty, _Alloc>::_Node _Node;
|
|
typedef typename _Alloc::_TEMPLATE_MEMBER
|
|
rebind<_Node>::other::pointer _Nodeptr;
|
|
|
|
_List_ptr(_Alloc _Al)
|
|
: _List_nod<_Ty, _Alloc>(_Al), _Alptr(_Al)
|
|
{ // construct base, and allocator from _Al
|
|
}
|
|
|
|
typename _Alloc::_TEMPLATE_MEMBER rebind<_Nodeptr>::other
|
|
_Alptr; // allocator object for pointers to nodes
|
|
};
|
|
|
|
// TEMPLATE CLASS _List_val
|
|
template<class _Ty,
|
|
class _Alloc>
|
|
class _List_val
|
|
: public _List_ptr<_Ty, _Alloc>
|
|
{ // base class for list to hold allocator _Alval
|
|
protected:
|
|
typedef typename _Alloc::_TEMPLATE_MEMBER rebind<_Ty>::other _Alty;
|
|
|
|
_List_val(_Alloc _Al = _Alloc())
|
|
: _List_ptr<_Ty, _Alloc>(_Al), _Alval(_Al)
|
|
{ // construct base, and allocator from _Al
|
|
}
|
|
|
|
_Alty _Alval; // allocator object for values stored in nodes
|
|
};
|
|
|
|
// TEMPLATE CLASS list
|
|
template<class _Ty,
|
|
class _Ax = allocator<_Ty> >
|
|
class list
|
|
: public _List_val<_Ty, _Ax>
|
|
{ // bidirectional linked list
|
|
public:
|
|
typedef list<_Ty, _Ax> _Myt;
|
|
typedef _List_val<_Ty, _Ax> _Mybase;
|
|
typedef typename _Mybase::_Alty _Alloc;
|
|
|
|
protected:
|
|
typedef typename _List_nod<_Ty, _Alloc>::_Genptr _Genptr;
|
|
typedef typename _List_nod<_Ty, _Alloc>::_Node _Node;
|
|
typedef _POINTER_X(_Node, _Alloc) _Nodeptr;
|
|
typedef _REFERENCE_X(_Nodeptr, _Alloc) _Nodepref;
|
|
typedef typename _Alloc::reference _Vref;
|
|
|
|
static _Nodepref _Next(_Nodeptr _Pnode)
|
|
{ // return reference to successor pointer in node
|
|
return ((_Nodepref)(*_Pnode)._Next);
|
|
}
|
|
|
|
static _Nodepref _Prev(_Nodeptr _Pnode)
|
|
{ // return reference to predecessor pointer in node
|
|
return ((_Nodepref)(*_Pnode)._Prev);
|
|
}
|
|
|
|
static _Vref _Myval(_Nodeptr _Pnode)
|
|
{ // return reference to value in node
|
|
return ((_Vref)(*_Pnode)._Myval);
|
|
}
|
|
|
|
public:
|
|
typedef _Alloc allocator_type;
|
|
typedef typename _Alloc::size_type size_type;
|
|
typedef typename _Alloc::difference_type _Dift;
|
|
typedef _Dift difference_type;
|
|
typedef typename _Alloc::pointer _Tptr;
|
|
typedef typename _Alloc::const_pointer _Ctptr;
|
|
typedef _Tptr pointer;
|
|
typedef _Ctptr const_pointer;
|
|
typedef typename _Alloc::reference _Reft;
|
|
typedef _Reft reference;
|
|
typedef typename _Alloc::const_reference const_reference;
|
|
typedef typename _Alloc::value_type value_type;
|
|
|
|
// CLASS const_iterator
|
|
class const_iterator;
|
|
friend class const_iterator;
|
|
|
|
class const_iterator
|
|
: public _Bidit<_Ty, _Dift, _Ctptr, const_reference>
|
|
{ // iterator for nonmutable list
|
|
public:
|
|
typedef bidirectional_iterator_tag iterator_category;
|
|
typedef _Ty value_type;
|
|
typedef _Dift difference_type;
|
|
typedef _Ctptr pointer;
|
|
typedef const_reference reference;
|
|
|
|
const_iterator()
|
|
: _Ptr(0)
|
|
{ // construct with null node pointer
|
|
}
|
|
|
|
const_iterator(_Nodeptr _Pnode)
|
|
: _Ptr(_Pnode)
|
|
{ // construct with node pointer _Pnode
|
|
}
|
|
|
|
const_reference operator*() const
|
|
{ // return designated value
|
|
return (_Myval(_Ptr));
|
|
}
|
|
|
|
_Ctptr operator->() const
|
|
{ // return pointer to class object
|
|
return (&**this);
|
|
}
|
|
|
|
const_iterator& operator++()
|
|
{ // preincrement
|
|
_Ptr = _Next(_Ptr);
|
|
return (*this);
|
|
}
|
|
|
|
const_iterator operator++(int)
|
|
{ // postincrement
|
|
const_iterator _Tmp = *this;
|
|
++*this;
|
|
return (_Tmp);
|
|
}
|
|
|
|
const_iterator& operator--()
|
|
{ // predecrement
|
|
_Ptr = _Prev(_Ptr);
|
|
return (*this);
|
|
}
|
|
|
|
const_iterator operator--(int)
|
|
{ // postdecrement
|
|
const_iterator _Tmp = *this;
|
|
--*this;
|
|
return (_Tmp);
|
|
}
|
|
|
|
bool operator==(const const_iterator& _Right) const
|
|
{ // test for iterator equality
|
|
return (_Ptr == _Right._Ptr);
|
|
}
|
|
|
|
bool operator!=(const const_iterator& _Right) const
|
|
{ // test for iterator inequality
|
|
return (!(*this == _Right));
|
|
}
|
|
|
|
_Nodeptr _Mynode() const
|
|
{ // return node pointer
|
|
return (_Ptr);
|
|
}
|
|
|
|
|
|
protected:
|
|
_Nodeptr _Ptr; // pointer to node
|
|
};
|
|
|
|
// CLASS iterator
|
|
class iterator;
|
|
friend class iterator;
|
|
|
|
class iterator
|
|
: public const_iterator
|
|
{ // iterator for mutable list
|
|
public:
|
|
typedef bidirectional_iterator_tag iterator_category;
|
|
typedef _Ty value_type;
|
|
typedef _Dift difference_type;
|
|
typedef _Tptr pointer;
|
|
typedef _Reft reference;
|
|
|
|
iterator()
|
|
: const_iterator(0)
|
|
{ // construct with null node
|
|
}
|
|
|
|
iterator(_Nodeptr _Pnode)
|
|
: const_iterator(_Pnode)
|
|
{ // construct with node pointer _Pnode
|
|
}
|
|
|
|
reference operator*() const
|
|
{ // return designated value
|
|
return (_Myval(_Ptr));
|
|
}
|
|
|
|
|
|
_Tptr operator->() const
|
|
{ // return pointer to class object
|
|
return (&**this);
|
|
}
|
|
|
|
iterator& operator++()
|
|
{ // preincrement
|
|
_Ptr = _Next(_Ptr);
|
|
return (*this);
|
|
}
|
|
|
|
iterator operator++(int)
|
|
{ // postincrement
|
|
iterator _Tmp = *this;
|
|
++*this;
|
|
return (_Tmp);
|
|
}
|
|
|
|
iterator& operator--()
|
|
{ // predecrement
|
|
_Ptr = _Prev(_Ptr);
|
|
return (*this);
|
|
}
|
|
|
|
iterator operator--(int)
|
|
{ // postdecrement
|
|
iterator _Tmp = *this;
|
|
--*this;
|
|
return (_Tmp);
|
|
}
|
|
};
|
|
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
|
|
|
list()
|
|
: _Mybase(), _Myhead(_Buynode()), _Mysize(0)
|
|
{ // construct empty list
|
|
}
|
|
|
|
explicit list(const _Alloc& _Al)
|
|
: _Mybase(_Al), _Myhead(_Buynode()), _Mysize(0)
|
|
{ // construct empty list, allocator
|
|
}
|
|
|
|
explicit list(size_type _Count)
|
|
: _Mybase(), _Myhead(0), _Mysize(0)
|
|
{ // construct list from _Count * _Ty()
|
|
_Ty _Val = _Ty(); // may throw
|
|
_Myhead = _Buynode();
|
|
_Construct_n(_Count, _Val);
|
|
}
|
|
|
|
list(size_type _Count, const _Ty& _Val)
|
|
: _Mybase(), _Myhead(_Buynode()), _Mysize(0)
|
|
{ // construct list from _Count * _Val
|
|
_Construct_n(_Count, _Val);
|
|
}
|
|
|
|
list(size_type _Count, const _Ty& _Val, const _Alloc& _Al)
|
|
: _Mybase(_Al), _Myhead(_Buynode()), _Mysize(0)
|
|
{ // construct list, allocator from _Count * _Val
|
|
_Construct_n(_Count, _Val);
|
|
}
|
|
|
|
list(const _Myt& _Right)
|
|
: _Mybase(_Right._Alval),
|
|
_Myhead(_Buynode()), _Mysize(0)
|
|
{ // construct list by copying _Right
|
|
_TRY_BEGIN
|
|
insert(begin(), _Right.begin(), _Right.end());
|
|
_CATCH_ALL
|
|
_Tidy();
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
template<class _Iter>
|
|
list(_Iter _First, _Iter _Last)
|
|
: _Mybase(), _Myhead(_Buynode()), _Mysize(0)
|
|
{ // construct list from [_First, _Last)
|
|
_Construct(_First, _Last, _Iter_cat(_First));
|
|
}
|
|
|
|
template<class _Iter>
|
|
list(_Iter _First, _Iter _Last, const _Alloc& _Al)
|
|
: _Mybase(_Al), _Myhead(_Buynode()), _Mysize(0)
|
|
{ // construct list, allocator from [_First, _Last)
|
|
_Construct(_First, _Last, _Iter_cat(_First));
|
|
}
|
|
|
|
template<class _Iter>
|
|
void _Construct(_Iter _Count, _Iter _Val, _Int_iterator_tag)
|
|
{ // construct list from _Count * _Val
|
|
_Construct_n((size_type)_Count, (_Ty)_Val);
|
|
}
|
|
|
|
template<class _Iter>
|
|
void _Construct(_Iter _First, _Iter _Last, input_iterator_tag)
|
|
{ // construct list from [_First, _Last), input iterators
|
|
_TRY_BEGIN
|
|
insert(begin(), _First, _Last);
|
|
_CATCH_ALL
|
|
_Tidy();
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
void _Construct_n(size_type _Count, const _Ty& _Val)
|
|
{ // construct from _Count * _Val
|
|
_TRY_BEGIN
|
|
_Insert_n(begin(), _Count, _Val);
|
|
_CATCH_ALL
|
|
_Tidy();
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
~list()
|
|
{ // destroy the object
|
|
_Tidy();
|
|
}
|
|
|
|
_Myt& operator=(const _Myt& _Right)
|
|
{ // assign _Right
|
|
if (this != &_Right)
|
|
assign(_Right.begin(), _Right.end());
|
|
return (*this);
|
|
}
|
|
|
|
iterator begin()
|
|
{ // return iterator for beginning of mutable sequence
|
|
return (iterator(_Myhead == 0 ? 0 : _Next(_Myhead)));
|
|
}
|
|
|
|
const_iterator begin() const
|
|
{ // return iterator for beginning of nonmutable sequence
|
|
return (const_iterator(_Myhead == 0 ? 0 : _Next(_Myhead)));
|
|
}
|
|
|
|
iterator end()
|
|
{ // return iterator for end of mutable sequence
|
|
return (iterator(_Myhead));
|
|
}
|
|
|
|
const_iterator end() const
|
|
{ // return iterator for end of nonmutable sequence
|
|
return (const_iterator(_Myhead));
|
|
}
|
|
|
|
reverse_iterator rbegin()
|
|
{ // return iterator for beginning of reversed mutable sequence
|
|
return (reverse_iterator(end()));
|
|
}
|
|
|
|
const_reverse_iterator rbegin() const
|
|
{ // return iterator for beginning of reversed nonmutable sequence
|
|
return (const_reverse_iterator(end()));
|
|
}
|
|
|
|
reverse_iterator rend()
|
|
{ // return iterator for end of reversed mutable sequence
|
|
return (reverse_iterator(begin()));
|
|
}
|
|
|
|
const_reverse_iterator rend() const
|
|
{ // return iterator for end of reversed nonmutable sequence
|
|
return (const_reverse_iterator(begin()));
|
|
}
|
|
|
|
void resize(size_type _Newsize)
|
|
{ // determine new length, padding with _Ty() elements as needed
|
|
resize(_Newsize, _Ty());
|
|
}
|
|
|
|
void resize(size_type _Newsize, _Ty _Val)
|
|
{ // determine new length, padding with _Val elements as needed
|
|
if (size() < _Newsize)
|
|
_Insert_n(end(), _Newsize - size(), _Val);
|
|
else
|
|
while (_Newsize < size())
|
|
pop_back();
|
|
}
|
|
|
|
size_type size() const
|
|
{ // return length of sequence
|
|
return (_Mysize);
|
|
}
|
|
|
|
size_type max_size() const
|
|
{ // return maximum possible length of sequence
|
|
return (this->_Alval.max_size());
|
|
}
|
|
|
|
bool empty() const
|
|
{ // test if sequence is empty
|
|
return (_Mysize == 0);
|
|
}
|
|
|
|
allocator_type get_allocator() const
|
|
{ // return allocator object for values
|
|
return (this->_Alval);
|
|
}
|
|
|
|
reference front()
|
|
{ // return first element of mutable sequence
|
|
return (*begin());
|
|
}
|
|
|
|
const_reference front() const
|
|
{ // return first element of nonmutable sequence
|
|
return (*begin());
|
|
}
|
|
|
|
reference back()
|
|
{ // return last element of mutable sequence
|
|
return (*(--end()));
|
|
}
|
|
|
|
const_reference back() const
|
|
{ // return last element of nonmutable sequence
|
|
return (*(--end()));
|
|
}
|
|
|
|
void push_front(const _Ty& _Val)
|
|
{ // insert element at beginning
|
|
_Insert(begin(), _Val);
|
|
}
|
|
|
|
void pop_front()
|
|
{ // erase element at beginning
|
|
erase(begin());
|
|
}
|
|
|
|
void push_back(const _Ty& _Val)
|
|
{ // insert element at end
|
|
_Insert(end(), _Val);
|
|
}
|
|
|
|
void pop_back()
|
|
{ // erase element at end
|
|
erase(--end());
|
|
}
|
|
|
|
template<class _Iter>
|
|
void assign(_Iter _First, _Iter _Last)
|
|
{ // assign [_First, _Last)
|
|
_Assign(_First, _Last, _Iter_cat(_First));
|
|
}
|
|
|
|
template<class _Iter>
|
|
void _Assign(_Iter _Count, _Iter _Val, _Int_iterator_tag)
|
|
{ // assign _Count * _Val
|
|
_Assign_n((size_type)_Count, (_Ty)_Val);
|
|
}
|
|
|
|
template<class _Iter>
|
|
void _Assign(_Iter _First, _Iter _Last, input_iterator_tag)
|
|
{ // assign [_First, _Last), input iterators
|
|
erase(begin(), end());
|
|
insert(begin(), _First, _Last);
|
|
}
|
|
|
|
void assign(size_type _Count, const _Ty& _Val)
|
|
{ // assign _Count * _Val
|
|
_Assign_n(_Count, _Val);
|
|
}
|
|
|
|
iterator insert(iterator _Where, const _Ty& _Val)
|
|
{ // insert _Val at _Where
|
|
_Insert(_Where, _Val);
|
|
return (--_Where);
|
|
}
|
|
|
|
void _Insert(iterator _Where, const _Ty& _Val)
|
|
{ // insert _Val at _Where
|
|
_Nodeptr _Pnode = _Where._Mynode();
|
|
_Nodeptr _Newnode = _Buynode(_Pnode, _Prev(_Pnode), _Val);
|
|
_Incsize(1);
|
|
_Prev(_Pnode) = _Newnode;
|
|
_Next(_Prev(_Newnode)) = _Newnode;
|
|
}
|
|
|
|
void insert(iterator _Where, size_type _Count, const _Ty& _Val)
|
|
{ // insert _Count * _Val at _Where
|
|
_Insert_n(_Where, _Count, _Val);
|
|
}
|
|
|
|
template<class _Iter>
|
|
void insert(iterator _Where, _Iter _First, _Iter _Last)
|
|
{ // insert [_First, _Last) at _Where
|
|
_Insert(_Where, _First, _Last, _Iter_cat(_First));
|
|
}
|
|
|
|
template<class _Iter>
|
|
void _Insert(iterator _Where, _Iter _Count, _Iter _Val,
|
|
_Int_iterator_tag)
|
|
{ // insert _Count * _Val at _Where
|
|
_Insert_n(_Where, (size_type)_Count, (_Ty)_Val);
|
|
}
|
|
|
|
template<class _Iter>
|
|
void _Insert(iterator _Where, _Iter _First, _Iter _Last,
|
|
input_iterator_tag)
|
|
{ // insert [_First, _Last) at _Where, input iterators
|
|
size_type _Num = 0;
|
|
|
|
_TRY_BEGIN
|
|
for (; _First != _Last; ++_First, ++_Num)
|
|
_Insert(_Where, *_First);
|
|
_CATCH_ALL
|
|
for (; 0 < _Num; --_Num)
|
|
{ // undo inserts
|
|
iterator _Before = _Where;
|
|
erase(--_Before);
|
|
}
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
template<class _Iter>
|
|
void _Insert(iterator _Where, _Iter _First, _Iter _Last,
|
|
forward_iterator_tag)
|
|
{ // insert [_First, _Last) at _Where, forward iterators
|
|
_Iter _Next = _First;
|
|
|
|
_TRY_BEGIN
|
|
for (; _First != _Last; ++_First)
|
|
_Insert(_Where, *_First);
|
|
_CATCH_ALL
|
|
for (; _Next != _First; ++_Next)
|
|
{ // undo inserts
|
|
iterator _Before = _Where;
|
|
erase(--_Before);
|
|
}
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
iterator erase(iterator _Where)
|
|
{ // erase element at _Where
|
|
_Nodeptr _Pnode = (_Where++)._Mynode();
|
|
if (_Pnode != _Myhead)
|
|
{ // not list head, safe to erase
|
|
_Next(_Prev(_Pnode)) = _Next(_Pnode);
|
|
_Prev(_Next(_Pnode)) = _Prev(_Pnode);
|
|
this->_Alnod.destroy(_Pnode);
|
|
this->_Alnod.deallocate(_Pnode, 1);
|
|
--_Mysize;
|
|
}
|
|
return (_Where);
|
|
}
|
|
|
|
iterator erase(iterator _First, iterator _Last)
|
|
{ // erase [_First, _Last)
|
|
while (_First != _Last)
|
|
erase(_First++);
|
|
return (_First);
|
|
}
|
|
|
|
void clear()
|
|
{ // erase all
|
|
erase(begin(), end());
|
|
}
|
|
|
|
void swap(_Myt& _Right)
|
|
{ // exchange contents with _Right
|
|
if (this->_Alval == _Right._Alval)
|
|
{ // same allocator, swap control information
|
|
std::swap(_Myhead, _Right._Myhead);
|
|
std::swap(_Mysize, _Right._Mysize);
|
|
}
|
|
else
|
|
{ // different allocator, do multiple assigns
|
|
iterator _Where = begin();
|
|
splice(_Where, _Right);
|
|
_Right.splice(_Right.begin(), *this, _Where, end());
|
|
}
|
|
}
|
|
|
|
void splice(iterator _Where, _Myt& _Right)
|
|
{ // splice all of _Right at _Where
|
|
if (this != &_Right && !_Right.empty())
|
|
{ // worth splicing, do it
|
|
_Splice(_Where, _Right, _Right.begin(), _Right.end(),
|
|
_Right._Mysize);
|
|
}
|
|
}
|
|
|
|
void splice(iterator _Where, _Myt& _Right, iterator _First)
|
|
{ // splice _Right [_First, _First + 1) at _Where
|
|
iterator _Last = _First;
|
|
if (_First != _Right.end() && _Where != _First && _Where != ++_Last)
|
|
{ // worth splicing, do it
|
|
_Splice(_Where, _Right, _First, _Last, 1);
|
|
}
|
|
}
|
|
|
|
void splice(iterator _Where, _Myt& _Right,
|
|
iterator _First, iterator _Last)
|
|
{ // splice _Right [_First, _Last) at _Where
|
|
if (_First != _Last && _Where != _Last)
|
|
{ // worth splicing, do it
|
|
size_type _Count = 0;
|
|
if (this == &_Right)
|
|
; // just rearrange this list
|
|
else if (_First == _Right.begin() && _Last == _Right.end())
|
|
_Count = _Right.size(); // splice in whole list
|
|
else
|
|
_Distance(_First, _Last, _Count); // splice in partial list
|
|
_Splice(_Where, _Right, _First, _Last, _Count);
|
|
}
|
|
}
|
|
|
|
void remove(const _Ty& _Val)
|
|
{ // erase each element matching _Val
|
|
iterator _Last = end();
|
|
for (iterator _First = begin(); _First != _Last; )
|
|
if (*_First == _Val)
|
|
erase(_First++);
|
|
else
|
|
++_First;
|
|
}
|
|
|
|
template<class _Pr1>
|
|
void remove_if(_Pr1 _Pred)
|
|
{ // erase each element satisfying _Pr1
|
|
iterator _Last = end();
|
|
for (iterator _First = begin(); _First != _Last; )
|
|
if (_Pred(*_First))
|
|
erase(_First++);
|
|
else
|
|
++_First;
|
|
}
|
|
|
|
void unique()
|
|
{ // erase each element matching previous
|
|
iterator _First = begin(), _Last = end();
|
|
if (_First != _Last)
|
|
for (iterator _Next = _First; ++_Next != _Last; _Next = _First)
|
|
if (*_First == *_Next)
|
|
erase(_Next);
|
|
else
|
|
_First = _Next;
|
|
}
|
|
|
|
template<class _Pr2>
|
|
void unique(_Pr2 _Pred)
|
|
{ // erase each element satisfying _Pred with previous
|
|
iterator _First = begin(), _Last = end();
|
|
if (_First != _Last)
|
|
for (iterator _Next = _First; ++_Next != _Last; _Next = _First)
|
|
if (_Pred(*_First, *_Next))
|
|
erase(_Next);
|
|
else
|
|
_First = _Next;
|
|
}
|
|
|
|
void merge(_Myt& _Right)
|
|
{ // merge in elements from _Right, both ordered by operator<
|
|
if (&_Right != this)
|
|
{ // safe to merge, do it
|
|
iterator _First1 = begin(), _Last1 = end();
|
|
iterator _First2 = _Right.begin(), _Last2 = _Right.end();
|
|
|
|
while (_First1 != _Last1 && _First2 != _Last2)
|
|
if (*_First2 < *_First1)
|
|
{ // splice in an element from _Right
|
|
iterator _Mid2 = _First2;
|
|
_Splice(_First1, _Right, _First2, ++_Mid2, 1);
|
|
_First2 = _Mid2;
|
|
}
|
|
else
|
|
++_First1;
|
|
|
|
if (_First2 != _Last2)
|
|
_Splice(_Last1, _Right, _First2, _Last2,
|
|
_Right._Mysize); // splice remainder of _Right
|
|
}
|
|
}
|
|
|
|
template<class _Pr3>
|
|
void merge(_Myt& _Right, _Pr3 _Pred)
|
|
{ // merge in elements from _Right, both ordered by _Pred
|
|
if (&_Right != this)
|
|
{ // safe to merge, do it
|
|
iterator _First1 = begin(), _Last1 = end();
|
|
iterator _First2 = _Right.begin(), _Last2 = _Right.end();
|
|
|
|
while (_First1 != _Last1 && _First2 != _Last2)
|
|
if (_Pred(*_First2, *_First1))
|
|
{ // splice in an element from _Right
|
|
iterator _Mid2 = _First2;
|
|
_Splice(_First1, _Right, _First2, ++_Mid2, 1);
|
|
_First2 = _Mid2;
|
|
}
|
|
else
|
|
++_First1;
|
|
|
|
if (_First2 != _Last2)
|
|
_Splice(_Last1, _Right, _First2, _Last2,
|
|
_Right._Mysize); // splice remainder of _Right
|
|
}
|
|
}
|
|
|
|
void sort()
|
|
{ // order sequence, using operator<
|
|
if (2 <= size())
|
|
{ // worth sorting, do it
|
|
const size_t _MAXBINS = 25;
|
|
_Myt _Templist(this->_Alval), _Binlist[_MAXBINS + 1];
|
|
size_t _Maxbin = 0;
|
|
|
|
while (!empty())
|
|
{ // sort another element, using bins
|
|
_Templist.splice(_Templist.begin(), *this, begin());
|
|
size_t _Bin;
|
|
|
|
for (_Bin = 0; _Bin < _Maxbin && !_Binlist[_Bin].empty();
|
|
++_Bin)
|
|
{ // merge into ever larger bins
|
|
_Binlist[_Bin].merge(_Templist);
|
|
_Binlist[_Bin].swap(_Templist);
|
|
}
|
|
|
|
if (_Bin == _MAXBINS)
|
|
_Binlist[_Bin - 1].merge(_Templist);
|
|
else
|
|
{ // spill to new bin, while they last
|
|
_Binlist[_Bin].swap(_Templist);
|
|
if (_Bin == _Maxbin)
|
|
++_Maxbin;
|
|
}
|
|
}
|
|
|
|
for (size_t _Bin = 1; _Bin < _Maxbin; ++_Bin)
|
|
_Binlist[_Bin].merge(_Binlist[_Bin - 1]); // merge up
|
|
swap(_Binlist[_Maxbin - 1]); // replace from last bin
|
|
}
|
|
}
|
|
|
|
template<class _Pr3>
|
|
void sort(_Pr3 _Pred)
|
|
{ // order sequence, using _Pred
|
|
if (2 <= size())
|
|
{ // worth sorting, do it
|
|
const size_t _MAXBINS = 25;
|
|
_Myt _Templist(this->_Alval), _Binlist[_MAXBINS + 1];
|
|
size_t _Maxbin = 0;
|
|
|
|
while (!empty())
|
|
{ // sort another element, using bins
|
|
_Templist.splice(_Templist.begin(), *this, begin());
|
|
size_t _Bin;
|
|
|
|
for (_Bin = 0; _Bin < _Maxbin && !_Binlist[_Bin].empty();
|
|
++_Bin)
|
|
{ // merge into ever larger bins
|
|
_Binlist[_Bin].merge(_Templist, _Pred);
|
|
_Binlist[_Bin].swap(_Templist);
|
|
}
|
|
|
|
if (_Bin == _MAXBINS)
|
|
_Binlist[_Bin - 1].merge(_Templist, _Pred);
|
|
else
|
|
{ // spill to new bin, while they last
|
|
_Binlist[_Bin].swap(_Templist);
|
|
if (_Bin == _Maxbin)
|
|
++_Maxbin;
|
|
}
|
|
}
|
|
|
|
for (size_t _Bin = 1; _Bin < _Maxbin; ++_Bin)
|
|
_Binlist[_Bin].merge(_Binlist[_Bin - 1],
|
|
_Pred); // merge up
|
|
swap(_Binlist[_Maxbin - 1]); // replace with last bin
|
|
}
|
|
}
|
|
|
|
void reverse()
|
|
{ // reverse sequence
|
|
if (2 <= size())
|
|
{ // worth doing
|
|
iterator _Last = end();
|
|
for (iterator _Next = ++begin(); _Next != _Last; )
|
|
{ // move next element to beginning
|
|
iterator _Before = _Next;
|
|
_Splice(begin(), *this, _Before, ++_Next, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected:
|
|
void _Assign_n(size_type _Count, const _Ty& _Val)
|
|
{ // assign _Count * _Val
|
|
_Ty _Tmp = _Val; // in case _Val is in sequence
|
|
erase(begin(), end());
|
|
_Insert_n(begin(), _Count, _Tmp);
|
|
}
|
|
|
|
_Nodeptr _Buynode()
|
|
{ // allocate a head node and set links
|
|
_Nodeptr _Pnode = this->_Alnod.allocate(1, (void *)0);
|
|
int _Linkcnt = 0;
|
|
|
|
_TRY_BEGIN
|
|
this->_Alptr.construct(&_Next(_Pnode), _Pnode);
|
|
++_Linkcnt;
|
|
this->_Alptr.construct(&_Prev(_Pnode), _Pnode);
|
|
_CATCH_ALL
|
|
if (0 < _Linkcnt)
|
|
this->_Alptr.destroy(&_Next(_Pnode));
|
|
this->_Alnod.deallocate(_Pnode, 1);
|
|
_RERAISE;
|
|
_CATCH_END
|
|
return (_Pnode);
|
|
}
|
|
|
|
_Nodeptr _Buynode(_Nodeptr _Next, _Nodeptr _Prev, const _Ty& _Val)
|
|
{ // allocate a node and set links
|
|
_Nodeptr _Pnode = this->_Alnod.allocate(1, (void *)0);
|
|
_TRY_BEGIN
|
|
new ((void *)_Pnode) _Node(_Next, _Prev, _Val);
|
|
_CATCH_ALL
|
|
this->_Alnod.deallocate(_Pnode, 1);
|
|
_RERAISE;
|
|
_CATCH_END
|
|
return (_Pnode);
|
|
}
|
|
|
|
void _Tidy()
|
|
{ // free all storage
|
|
erase(begin(), end());
|
|
this->_Alptr.destroy(&_Next(_Myhead));
|
|
this->_Alptr.destroy(&_Prev(_Myhead));
|
|
this->_Alnod.deallocate(_Myhead, 1);
|
|
_Myhead = 0, _Mysize = 0;
|
|
}
|
|
|
|
void _Insert_n(iterator _Where, size_type _Count, const _Ty& _Val)
|
|
{ // insert _Count * _Val at _Where
|
|
size_type _Countsave = _Count;
|
|
|
|
_TRY_BEGIN
|
|
for (; 0 < _Count; --_Count)
|
|
_Insert(_Where, _Val);
|
|
_CATCH_ALL
|
|
for (; _Count < _Countsave; ++_Count)
|
|
{ // undo inserts
|
|
iterator _Before = _Where;
|
|
erase(--_Before);
|
|
}
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
void _Splice(iterator _Where, _Myt& _Right,
|
|
iterator _First, iterator _Last, size_type _Count)
|
|
{ // splice _Right [_First, _Last) before _Where
|
|
if (this->_Alval == _Right._Alval)
|
|
{ // same allocator, just relink
|
|
if (this != &_Right)
|
|
{ // splicing from another list, adjust counts
|
|
_Incsize(_Count);
|
|
_Right._Mysize -= _Count;
|
|
}
|
|
_Next(_Prev(_First._Mynode())) = _Last._Mynode();
|
|
_Next(_Prev(_Last._Mynode())) = _Where._Mynode();
|
|
_Next(_Prev(_Where._Mynode())) = _First._Mynode();
|
|
_Nodeptr _Pnode = _Prev(_Where._Mynode());
|
|
_Prev(_Where._Mynode()) = _Prev(_Last._Mynode());
|
|
_Prev(_Last._Mynode()) = _Prev(_First._Mynode());
|
|
_Prev(_First._Mynode()) = _Pnode;
|
|
}
|
|
else
|
|
{ // different allocator, copy nodes then erase source
|
|
insert(_Where, _First, _Last);
|
|
_Right.erase(_First, _Last);
|
|
}
|
|
}
|
|
|
|
void _Incsize(size_type _Count)
|
|
{ // alter element count, with checking
|
|
if (max_size() - size() < _Count)
|
|
_THROW(length_error, "list<T> too long");
|
|
_Mysize += _Count;
|
|
}
|
|
|
|
_Nodeptr _Myhead; // pointer to head node
|
|
size_type _Mysize; // number of elements
|
|
};
|
|
|
|
// list TEMPLATE FUNCTIONS
|
|
template<class _Ty, class _Alloc> inline
|
|
bool operator==(const list<_Ty, _Alloc>& _Left,
|
|
const list<_Ty, _Alloc>& _Right)
|
|
{ // test for list equality
|
|
return (_Left.size() == _Right.size()
|
|
&& equal(_Left.begin(), _Left.end(), _Right.begin()));
|
|
}
|
|
|
|
template<class _Ty, class _Alloc> inline
|
|
bool operator!=(const list<_Ty, _Alloc>& _Left,
|
|
const list<_Ty, _Alloc>& _Right)
|
|
{ // test for list inequality
|
|
return (!(_Left == _Right));
|
|
}
|
|
|
|
template<class _Ty, class _Alloc> inline
|
|
bool operator<(const list<_Ty, _Alloc>& _Left,
|
|
const list<_Ty, _Alloc>& _Right)
|
|
{ // test if _Left < _Right for lists
|
|
return (lexicographical_compare(_Left.begin(), _Left.end(),
|
|
_Right.begin(), _Right.end()));
|
|
}
|
|
|
|
template<class _Ty, class _Alloc> inline
|
|
bool operator>(const list<_Ty, _Alloc>& _Left,
|
|
const list<_Ty, _Alloc>& _Right)
|
|
{ // test if _Left > _Right for lists
|
|
return (_Right < _Left);
|
|
}
|
|
|
|
template<class _Ty, class _Alloc> inline
|
|
bool operator<=(const list<_Ty, _Alloc>& _Left,
|
|
const list<_Ty, _Alloc>& _Right)
|
|
{ // test if _Left <= _Right for lists
|
|
return (!(_Right < _Left));
|
|
}
|
|
|
|
template<class _Ty, class _Alloc> inline
|
|
bool operator>=(const list<_Ty, _Alloc>& _Left,
|
|
const list<_Ty, _Alloc>& _Right)
|
|
{ // test if _Left >= _Right for lists
|
|
return (!(_Left < _Right));
|
|
}
|
|
|
|
template<class _Ty, class _Alloc> inline
|
|
void swap(list<_Ty, _Alloc>& _Left, list<_Ty, _Alloc>& _Right)
|
|
{ // swap _Left and _Right lists
|
|
_Left.swap(_Right);
|
|
}
|
|
|
|
_STD_END
|
|
#pragma warning(pop)
|
|
#pragma pack(pop)
|
|
|
|
#endif /* _LIST_ */
|
|
|
|
/*
|
|
* Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
|
|
* Consult your license regarding permissions and restrictions.
|
|
*/
|
|
|
|
/*
|
|
* This file is derived from software bearing the following
|
|
* restrictions:
|
|
*
|
|
* 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.
|
|
V3.10:0009 */
|