#if __cplusplus >= 201103L
#include <initializer_list>
#include <bits/allocated_ptr.h>
+#include <bits/ptr_traits.h>
#include <ext/aligned_buffer.h>
#endif
#if __glibcxx_ranges_to_container // C++ >= 23
# include <bits/ranges_util.h> // ranges::subrange
#endif
+#if __cplusplus < 201103L
+# undef _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
+# define _GLIBCXX_USE_ALLOC_PTR_FOR_LIST 0
+#elif ! defined _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
+# define _GLIBCXX_USE_ALLOC_PTR_FOR_LIST 1
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Common part of a node in the %list.
struct _List_node_base
{
+ typedef _List_node_base* _Base_ptr;
+
_List_node_base* _M_next;
_List_node_base* _M_prev;
void
_M_unhook() _GLIBCXX_USE_NOEXCEPT;
+
+ _List_node_base* _M_base() { return this; }
+ const _List_node_base* _M_base() const { return this; }
};
struct _List_size
#endif
};
-
/// The %list node header.
struct _List_node_header : public _List_node_base, _List_size
{
_List_size::operator=(_List_size());
}
+ using _List_node_base::_M_base;
+#if ! _GLIBCXX_INLINE_VERSION
+ _List_node_base* _M_base() { return this; } // XXX GLIBCXX_ABI Deprecated
+#endif
+ };
+
+ } // namespace detail
+
+#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
+_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+_GLIBCXX_BEGIN_NAMESPACE_CXX11
+ template<typename _Tp, typename _Allocator> class list;
+_GLIBCXX_END_NAMESPACE_CXX11
+_GLIBCXX_END_NAMESPACE_CONTAINER
+
+namespace __list
+{
+ // The base class for a list node. Contains the pointers connecting nodes.
+ template<typename _VoidPtr>
+ struct _Node_base
+ {
+ using _Base_ptr = __ptr_rebind<_VoidPtr, _Node_base>;
+ _Base_ptr _M_next;
+ _Base_ptr _M_prev;
+
+ static void
+ swap(_Node_base& __x, _Node_base& __y) noexcept;
+
+ void
+ _M_transfer(_Base_ptr const __first, _Base_ptr const __last);
+
+ void
+ _M_hook(_Base_ptr const __position) noexcept
+ {
+ auto __self = pointer_traits<_Base_ptr>::pointer_to(*this);
+ this->_M_next = __position;
+ this->_M_prev = __position->_M_prev;
+ __position->_M_prev->_M_next = __self;
+ __position->_M_prev = __self;
+ }
+
+ void
+ _M_unhook() noexcept
+ {
+ auto const __next_node = this->_M_next;
+ auto const __prev_node = this->_M_prev;
+ __prev_node->_M_next = __next_node;
+ __next_node->_M_prev = __prev_node;
+ }
+
+ // This is not const-correct, but it's only used in a const access path
+ // by std::list::empty(), where it doesn't escape, and by
+ // std::list::end() const, where the pointer is used to initialize a
+ // const_iterator and so constness is restored.
+ _Base_ptr
+ _M_base() const noexcept
+ {
+ return pointer_traits<_Base_ptr>::
+ pointer_to(const_cast<_Node_base&>(*this));
+ }
+ };
+
+ using ::std::__detail::_List_size;
+
+ // The special sentinel node contained by a std::list.
+ // begin()->_M_node->_M_prev and end()->_M_node point to this header.
+ // This is not a complete node, as it doesn't contain a value.
+ template<typename _VoidPtr>
+ struct _Node_header
+ : public _Node_base<_VoidPtr>, _List_size
+ {
+ _Node_header() noexcept
+ { _M_init(); }
+
+ _Node_header(_Node_header&& __x) noexcept
+ : _Node_base<_VoidPtr>(__x), _List_size(__x)
+ {
+ if (__x._M_base()->_M_next == __x._M_base())
+ this->_M_next = this->_M_prev = this->_M_base();
+ else
+ {
+ this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base();
+ __x._M_init();
+ }
+ }
+
+ void
+ _M_move_nodes(_Node_header&& __x) noexcept
+ {
+ auto const __xnode = __x._M_base();
+ if (__xnode->_M_next == __xnode)
+ _M_init();
+ else
+ {
+ auto const __node = this->_M_base();
+ __node->_M_next = __xnode->_M_next;
+ __node->_M_prev = __xnode->_M_prev;
+ __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
+ _List_size::operator=(__x);
+ __x._M_init();
+ }
+ }
+
+ void
+ _M_init() noexcept
+ {
+ this->_M_next = this->_M_prev = this->_M_base();
+ _List_size::operator=(_List_size());
+ }
+
+ void _M_reverse() noexcept;
+ };
+
+ // The node type used for allocators with fancy pointers.
+ template<typename _ValPtr>
+ struct _Node : public __list::_Node_base<__ptr_rebind<_ValPtr, void>>
+ {
+ using value_type = typename pointer_traits<_ValPtr>::element_type;
+ using _Node_ptr = __ptr_rebind<_ValPtr, _Node>;
+
+ union {
+ value_type _M_data;
+ };
+
+ _Node() { }
+ ~_Node() { }
+ _Node(_Node&&) = delete;
+
+ value_type* _M_valptr() { return std::__addressof(_M_data); }
+ value_type const* _M_valptr() const { return std::__addressof(_M_data); }
+
+ _Node_ptr
+ _M_node_ptr()
+ { return pointer_traits<_Node_ptr>::pointer_to(*this); }
+ };
+
+ template<bool _Const, typename _Ptr> class _Iterator;
+
+ template<bool _Const, typename _Ptr>
+ class _Iterator
+ {
+ using _Node = __list::_Node<_Ptr>;
+ using _Base_ptr
+ = typename __list::_Node_base<__ptr_rebind<_Ptr, void>>::_Base_ptr;
+
+ template<typename _Tp>
+ using __maybe_const = __conditional_t<_Const, const _Tp, _Tp>;
+
+ public:
+ using value_type = typename pointer_traits<_Ptr>::element_type;
+ using difference_type = ptrdiff_t;
+ using iterator_category = bidirectional_iterator_tag;
+ using pointer = __maybe_const<value_type>*;
+ using reference = __maybe_const<value_type>&;
+
+ constexpr _Iterator() noexcept : _M_node() { }
+
+ _Iterator(const _Iterator&) = default;
+ _Iterator& operator=(const _Iterator&) = default;
+
+#ifdef __glibcxx_concepts
+ constexpr
+ _Iterator(const _Iterator<false, _Ptr>& __i) requires _Const
+#else
+ template<bool _OtherConst,
+ typename = __enable_if_t<_Const && !_OtherConst>>
+ constexpr
+ _Iterator(const _Iterator<_OtherConst, _Ptr>& __i)
+#endif
+ : _M_node(__i._M_node) { }
+
+ constexpr explicit
+ _Iterator(_Base_ptr __x) noexcept
+ : _M_node(__x) { }
+
+ // Must downcast from _Node_base to _Node to get to value.
+ [[__nodiscard__]]
+ constexpr reference
+ operator*() const noexcept
+ { return static_cast<_Node&>(*_M_node)._M_data; }
+
+ [[__nodiscard__]]
+ constexpr pointer
+ operator->() const noexcept
+ { return std::__addressof(operator*()); }
+
+ _GLIBCXX14_CONSTEXPR _Iterator&
+ operator++() noexcept
+ {
+ _M_node = _M_node->_M_next;
+ return *this;
+ }
+
+ _GLIBCXX14_CONSTEXPR _Iterator
+ operator++(int) noexcept
+ {
+ auto __tmp = *this;
+ _M_node = _M_node->_M_next;
+ return __tmp;
+ }
+
+ _GLIBCXX14_CONSTEXPR _Iterator&
+ operator--() noexcept
+ {
+ _M_node = _M_node->_M_prev;
+ return *this;
+ }
+
+ _GLIBCXX14_CONSTEXPR _Iterator
+ operator--(int) noexcept
+ {
+ auto __tmp = *this;
+ _M_node = _M_node->_M_prev;
+ return __tmp;
+ }
+
+ [[__nodiscard__]]
+ friend constexpr bool
+ operator==(const _Iterator& __x, const _Iterator& __y) noexcept
+ { return __x._M_node == __y._M_node; }
+
+#if __cpp_impl_three_way_comparison < 201907L
+ [[__nodiscard__]]
+ friend constexpr bool
+ operator!=(const _Iterator& __x, const _Iterator& __y) noexcept
+ { return __x._M_node != __y._M_node; }
+#endif
+
private:
- _List_node_base* _M_base() { return this; }
+ template<typename _Tp, typename _Allocator>
+ friend class _GLIBCXX_STD_C::list;
+
+ friend _Iterator<!_Const, _Ptr>;
+
+ constexpr _Iterator<false, _Ptr>
+ _M_const_cast() const noexcept
+ { return _Iterator<false, _Ptr>(_M_node); }
+
+ _Base_ptr _M_node;
+ };
+} // namespace __list
+#endif // USE_ALLOC_PTR_FOR_LIST
+
+_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+ template<typename _Tp> struct _List_node;
+ template<typename _Tp> struct _List_iterator;
+ template<typename _Tp> struct _List_const_iterator;
+_GLIBCXX_END_NAMESPACE_CONTAINER
+
+namespace __list
+{
+ // Determine the node and iterator types used by std::list.
+ template<typename _Tp, typename _Ptr>
+ struct _Node_traits;
+
+#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST <= 9000
+ // Specialization for the simple case where the allocator's pointer type
+ // is the same type as value_type*.
+ // For ABI compatibility we can't change the types used for this case.
+ template<typename _Tp>
+ struct _Node_traits<_Tp, _Tp*>
+ {
+ typedef __detail::_List_node_base _Node_base;
+ typedef __detail::_List_node_header _Node_header;
+ typedef _GLIBCXX_STD_C::_List_node<_Tp> _Node;
+ typedef _GLIBCXX_STD_C::_List_iterator<_Tp> _Iterator;
+ typedef _GLIBCXX_STD_C::_List_const_iterator<_Tp> _Const_iterator;
+ };
+#endif
+
+#if ! _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
+ // Always use the T* specialization.
+ template<typename _Tp, typename _Ptr>
+ struct _Node_traits
+ : _Node_traits<_Tp, _Tp*>
+ { };
+#else
+ // Primary template used when the allocator uses fancy pointers.
+ template<typename _Tp, typename _Ptr>
+ struct _Node_traits
+ {
+ private:
+ using _VoidPtr = __ptr_rebind<_Ptr, void>;
+ using _ValPtr = __ptr_rebind<_Ptr, _Tp>;
+
+ public:
+ using _Node_base = __list::_Node_base<_VoidPtr>;
+ using _Node_header = __list::_Node_header<_VoidPtr>;
+ using _Node = __list::_Node<_ValPtr>;
+ using _Iterator = __list::_Iterator<false, _ValPtr>;
+ using _Const_iterator = __list::_Iterator<true, _ValPtr>;
};
+#endif // USE_ALLOC_PTR_FOR_LIST
- // Used by list::sort to hold nodes being sorted.
- struct _Scratch_list : _List_node_base
+ // Used by std::list::sort to hold nodes being sorted.
+ template<typename _NodeBaseT>
+ struct _Scratch_list
+ : _NodeBaseT
{
- _Scratch_list() { _M_next = _M_prev = this; }
+ typedef _NodeBaseT _Base;
+ typedef typename _Base::_Base_ptr _Base_ptr;
- bool empty() const { return _M_next == this; }
+ _Scratch_list() { this->_M_next = this->_M_prev = this->_M_base(); }
- void swap(_List_node_base& __l) { _List_node_base::swap(*this, __l); }
+ bool empty() const { return this->_M_next == this->_M_base(); }
+
+ void swap(_Base& __l) { _Base::swap(*this, __l); }
template<typename _Iter, typename _Cmp>
struct _Ptr_cmp
_Cmp _M_cmp;
bool
- operator()(__detail::_List_node_base* __lhs,
- __detail::_List_node_base* __rhs) /* not const */
+ operator()(_Base_ptr __lhs, _Base_ptr __rhs) /* not const */
{ return _M_cmp(*_Iter(__lhs), *_Iter(__rhs)); }
};
struct _Ptr_cmp<_Iter, void>
{
bool
- operator()(__detail::_List_node_base* __lhs,
- __detail::_List_node_base* __rhs) const
+ operator()(_Base_ptr __lhs, _Base_ptr __rhs) const
{ return *_Iter(__lhs) < *_Iter(__rhs); }
};
// Merge nodes from __x into *this. Both lists must be sorted wrt _Cmp.
template<typename _Cmp>
void
- merge(_List_node_base& __x, _Cmp __comp)
+ merge(_Base& __x, _Cmp __comp)
{
- _List_node_base* __first1 = _M_next;
- _List_node_base* const __last1 = this;
- _List_node_base* __first2 = __x._M_next;
- _List_node_base* const __last2 = std::__addressof(__x);
+ _Base_ptr __first1 = this->_M_next;
+ _Base_ptr const __last1 = this->_M_base();
+ _Base_ptr __first2 = __x._M_next;
+ _Base_ptr const __last2 = __x._M_base();
while (__first1 != __last1 && __first2 != __last2)
{
if (__comp(__first2, __first1))
{
- _List_node_base* __next = __first2->_M_next;
+ _Base_ptr __next = __first2->_M_next;
__first1->_M_transfer(__first2, __next);
__first2 = __next;
}
}
// Splice the node at __i into *this.
- void _M_take_one(_List_node_base* __i)
+ void _M_take_one(_Base_ptr __i)
{ this->_M_transfer(__i, __i->_M_next); }
// Splice all nodes from *this after __i.
- void _M_put_all(_List_node_base* __i)
+ void _M_put_all(_Base_ptr __i)
{
if (!empty())
- __i->_M_transfer(_M_next, this);
+ __i->_M_transfer(this->_M_next, this->_M_base());
}
};
-
- } // namespace detail
+} // namespace __list
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp>
struct _List_node : public __detail::_List_node_base
{
+ typedef _List_node* _Node_ptr;
+
#if __cplusplus >= 201103L
__gnu_cxx::__aligned_membuf<_Tp> _M_storage;
_Tp* _M_valptr() { return _M_storage._M_ptr(); }
_Tp* _M_valptr() { return std::__addressof(_M_data); }
_Tp const* _M_valptr() const { return std::__addressof(_M_data); }
#endif
+
+ _Node_ptr _M_node_ptr() { return this; }
};
/**
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
rebind<_Tp>::other _Tp_alloc_type;
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tp_alloc_traits;
+
+ typedef __list::_Node_traits<_Tp, typename _Tp_alloc_traits::pointer>
+ _Node_traits;
typedef typename _Tp_alloc_traits::template
- rebind<_List_node<_Tp> >::other _Node_alloc_type;
+ rebind<typename _Node_traits::_Node>::other _Node_alloc_type;
typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
struct _List_impl
: public _Node_alloc_type
{
- __detail::_List_node_header _M_node;
+ typename _Node_traits::_Node_header _M_node;
_List_impl() _GLIBCXX_NOEXCEPT_IF(
is_nothrow_default_constructible<_Node_alloc_type>::value)
_M_get_node()
{ return _Node_alloc_traits::allocate(_M_impl, 1); }
+#if __cplusplus < 201103L || _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
void
_M_put_node(typename _Node_alloc_traits::pointer __p) _GLIBCXX_NOEXCEPT
{ _Node_alloc_traits::deallocate(_M_impl, __p, 1); }
+#else
+ void
+ _M_put_node(_List_node<_Tp>* __p)
+ {
+ // When not using the allocator's pointer type internally we must
+ // convert between _Node_ptr (i.e. _List_node*) and the allocator's
+ // pointer type.
+ using __alloc_pointer = typename _Node_alloc_traits::pointer;
+ auto __ap = pointer_traits<__alloc_pointer>::pointer_to(*__p);
+ _Node_alloc_traits::deallocate(_M_impl, __ap, 1);
+ }
+#endif
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+ void
+ _M_destroy_node(typename _Node_alloc_traits::pointer __p)
+ {
+#if __cplusplus >= 201103L
+ // Destroy the element
+ _Node_alloc_traits::destroy(_M_impl, __p->_M_valptr());
+ // Only destroy the node if the pointers require it.
+ using _Node = typename _Node_traits::_Node;
+ using _Base_ptr = typename _Node_traits::_Node_base::_Base_ptr;
+ if constexpr (!is_trivially_destructible<_Base_ptr>::value)
+ __p->~_Node();
+#else
+ _Tp_alloc_type(_M_impl).destroy(__p->_M_valptr());
+#endif
+ this->_M_put_node(__p);
+ }
+#pragma GCC diagnostic pop
public:
typedef _Alloc allocator_type;
// so that explicit instantiation declarations of std::list that were
// compiled with old versions of GCC can still find these old symbols.
+ // Use 'if constexpr' so that the functions don't do anything for
+ // specializations using _Node_traits<T, fancy-pointer>, because any
+ // old code referencing these symbols wasn't using the fancy-pointer
+ // specializations.
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+
# if __cplusplus >= 201103L
_List_base(_List_base&& __x, _Node_alloc_type&& __a)
: _M_impl(std::move(__a))
{
- if (__x._M_get_Node_allocator() == _M_get_Node_allocator())
- _M_move_nodes(std::move(__x));
- // else caller must move individual elements.
+#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
+ if constexpr (is_same<typename _Tp_alloc_traits::pointer, _Tp*>::value)
+#endif
+ if (__x._M_get_Node_allocator() == _M_get_Node_allocator())
+ _M_move_nodes(std::move(__x));
+ // else caller must move individual elements.
}
# endif
_S_distance(const __detail::_List_node_base* __first,
const __detail::_List_node_base* __last)
{
- size_t __n = 0;
- while (__first != __last)
+#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
+ if constexpr (!is_same<typename _Tp_alloc_traits::pointer, _Tp*>::value)
+ return 0;
+ else
+#endif
{
- __first = __first->_M_next;
- ++__n;
+ size_t __n = 0;
+ while (__first != __last)
+ {
+ __first = __first->_M_next;
+ ++__n;
+ }
+ return __n;
}
- return __n;
}
#if _GLIBCXX_USE_CXX11_ABI
// count the number of nodes
size_t _M_node_count() const
{
- return _S_distance(_M_impl._M_node._M_next,
- std::__addressof(_M_impl._M_node));
+ return _S_distance(_M_impl._M_node._M_next, _M_impl._M_node._M_base());
}
#endif
+#pragma GCC diagnostic pop
#endif // ! INLINE_VERSION
};
typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits;
typedef typename _Base::_Node_alloc_type _Node_alloc_type;
typedef typename _Base::_Node_alloc_traits _Node_alloc_traits;
+ typedef typename _Base::_Node_traits _Node_traits;
public:
typedef _Tp value_type;
typedef typename _Tp_alloc_traits::const_pointer const_pointer;
typedef typename _Tp_alloc_traits::reference reference;
typedef typename _Tp_alloc_traits::const_reference const_reference;
- typedef _List_iterator<_Tp> iterator;
- typedef _List_const_iterator<_Tp> const_iterator;
+ typedef typename _Node_traits::_Iterator iterator;
+ typedef typename _Node_traits::_Const_iterator const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef size_t size_type;
protected:
// Note that pointers-to-_Node's can be ctor-converted to
// iterator types.
- typedef _List_node<_Tp> _Node;
+ typedef typename _Node_alloc_traits::pointer _Node_ptr;
using _Base::_M_impl;
using _Base::_M_put_node;
* @a __args in it.
*/
#if __cplusplus < 201103L
- _Node*
+ _Node_ptr
_M_create_node(const value_type& __x)
{
- _Node* __p = this->_M_get_node();
+ _Node_ptr __p = this->_M_get_node();
__try
{
_Tp_alloc_type __alloc(_M_get_Node_allocator());
}
#else
template<typename... _Args>
- _Node*
+ _Node_ptr
_M_create_node(_Args&&... __args)
{
- auto __p = this->_M_get_node();
auto& __alloc = _M_get_Node_allocator();
- __allocated_ptr<_Node_alloc_type> __guard{__alloc, __p};
- _Node_alloc_traits::construct(__alloc, __p->_M_valptr(),
+ auto __guard = std::__allocate_guarded_obj(__alloc);
+ _Node_alloc_traits::construct(__alloc, __guard->_M_valptr(),
std::forward<_Args>(__args)...);
- __guard = nullptr;
+ auto __p = __guard.release();
+#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
return __p;
+#else
+ return std::__to_address(__p);
+#endif
}
#endif
_GLIBCXX_NODISCARD
iterator
end() _GLIBCXX_NOEXCEPT
- { return iterator(&this->_M_impl._M_node); }
+ { return iterator(this->_M_impl._M_node._M_base()); }
/**
* Returns a read-only (constant) iterator that points one past
_GLIBCXX_NODISCARD
const_iterator
end() const _GLIBCXX_NOEXCEPT
- { return const_iterator(&this->_M_impl._M_node); }
+ { return const_iterator(this->_M_impl._M_node._M_base()); }
/**
* Returns a read/write reverse iterator that points to the last
[[__nodiscard__]]
const_iterator
cend() const noexcept
- { return const_iterator(&this->_M_impl._M_node); }
+ { return const_iterator(this->_M_impl._M_node._M_base()); }
/**
* Returns a read-only (constant) reverse iterator that points to
*/
_GLIBCXX_NODISCARD bool
empty() const _GLIBCXX_NOEXCEPT
- { return this->_M_impl._M_node._M_next == &this->_M_impl._M_node; }
+ {
+ return this->_M_impl._M_node._M_next == this->_M_impl._M_node._M_base();
+ }
/** Returns the number of elements in the %list. */
_GLIBCXX_NODISCARD
void
swap(list& __x) _GLIBCXX_NOEXCEPT
{
- __detail::_List_node_base::swap(this->_M_impl._M_node,
- __x._M_impl._M_node);
+ _Node_traits::_Node_base::swap(this->_M_impl._M_node,
+ __x._M_impl._M_node);
size_t __xsize = __x._M_get_size();
__x._M_set_size(this->_M_get_size());
void
_M_insert(iterator __position, const value_type& __x)
{
- _Node* __tmp = _M_create_node(__x);
+ _Node_ptr __tmp = _M_create_node(__x);
__tmp->_M_hook(__position._M_node);
this->_M_inc_size(1);
}
void
_M_insert(iterator __position, _Args&&... __args)
{
- _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...);
+ _Node_ptr __tmp = _M_create_node(std::forward<_Args>(__args)...);
__tmp->_M_hook(__position._M_node);
this->_M_inc_size(1);
}
void
_M_erase(iterator __position) _GLIBCXX_NOEXCEPT
{
+ typedef typename _Node_traits::_Node _Node;
this->_M_dec_size(1);
__position._M_node->_M_unhook();
- _Node* __n = static_cast<_Node*>(__position._M_node);
-#if __cplusplus >= 201103L
- _Node_alloc_traits::destroy(_M_get_Node_allocator(), __n->_M_valptr());
-#else
- _Tp_alloc_type(_M_get_Node_allocator()).destroy(__n->_M_valptr());
-#endif
-
- _M_put_node(__n);
+ _Node& __n = static_cast<_Node&>(*__position._M_node);
+ this->_M_destroy_node(__n._M_node_ptr());
}
// To implement the splice (and merge) bits of N1599.
}
return __n;
}
+
+#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
+ template<bool _Const, typename _Ptr>
+ inline ptrdiff_t
+ __distance(__list::_Iterator<_Const, _Ptr> __first,
+ __list::_Iterator<_Const, _Ptr> __last,
+ input_iterator_tag __tag)
+ {
+ using _Tp = typename __list::_Iterator<_Const, _Ptr>::value_type;
+ using _Sentinel = typename __list::_Node_traits<_Tp, _Ptr>::_Node_header;
+ auto __beyond = __last;
+ ++__beyond;
+ const bool __whole = __first == __beyond;
+ if (__builtin_constant_p (__whole) && __whole)
+ return static_cast<const _Sentinel&>(*__last._M_node)._M_size;
+
+ ptrdiff_t __n = 0;
+ while (__first != __last)
+ {
+ ++__first;
+ ++__n;
+ }
+ return __n;
+ }
+#endif
+#endif
+
+#if _GLIBCXX_USE_ALLOC_PTR_FOR_LIST
+namespace __list
+{
+ template<typename _VoidPtr>
+ void
+ _Node_base<_VoidPtr>::swap(_Node_base& __x, _Node_base& __y) noexcept
+ {
+ auto __px = pointer_traits<_Base_ptr>::pointer_to(__x);
+ auto __py = pointer_traits<_Base_ptr>::pointer_to(__y);
+
+ if (__x._M_next != __px)
+ {
+ if (__y._M_next != __py)
+ {
+ using std::swap;
+ // Both __x and __y are not empty.
+ swap(__x._M_next,__y._M_next);
+ swap(__x._M_prev,__y._M_prev);
+ __x._M_next->_M_prev = __x._M_prev->_M_next = __px;
+ __y._M_next->_M_prev = __y._M_prev->_M_next = __py;
+ }
+ else
+ {
+ // __x is not empty, __y is empty.
+ __y._M_next = __x._M_next;
+ __y._M_prev = __x._M_prev;
+ __y._M_next->_M_prev = __y._M_prev->_M_next = __py;
+ __x._M_next = __x._M_prev = __px;
+ }
+ }
+ else if (__y._M_next != __py)
+ {
+ // __x is empty, __y is not empty.
+ __x._M_next = __y._M_next;
+ __x._M_prev = __y._M_prev;
+ __x._M_next->_M_prev = __x._M_prev->_M_next = __px;
+ __y._M_next = __y._M_prev = __py;
+ }
+ }
+
+ template<typename _VoidPtr>
+ void
+ _Node_base<_VoidPtr>::_M_transfer(_Base_ptr const __first,
+ _Base_ptr const __last)
+ {
+ __glibcxx_assert(__first != __last);
+
+ auto __self = pointer_traits<_Base_ptr>::pointer_to(*this);
+ if (__self != __last)
+ {
+ // Remove [first, last) from its old position.
+ __last->_M_prev->_M_next = __self;
+ __first->_M_prev->_M_next = __last;
+ this->_M_prev->_M_next = __first;
+
+ // Splice [first, last) into its new position.
+ auto const __tmp = this->_M_prev;
+ this->_M_prev = __last->_M_prev;
+ __last->_M_prev = __first->_M_prev;
+ __first->_M_prev = __tmp;
+ }
+ }
+
+ template<typename _VoidPtr>
+ void
+ _Node_header<_VoidPtr>::_M_reverse() noexcept
+ {
+ const auto __self = this->_M_base();
+ auto __tmp = __self;
+ do
+ {
+ using std::swap;
+ swap(__tmp->_M_next, __tmp->_M_prev);
+
+ // Old next node is now prev.
+ __tmp = __tmp->_M_prev;
+ }
+ while (__tmp != __self);
+ }
+} // namespace __list
#endif
_GLIBCXX_END_NAMESPACE_VERSION