__tree(const value_compare& __comp, const allocator_type& __a);
__tree(const __tree& __t);
__tree& operator=(const __tree& __t);
- template <class _InputIterator>
- void __assign_unique(_InputIterator __first, _InputIterator __last);
+ template <class _ForwardIterator>
+ void __assign_unique(_ForwardIterator __first, _ForwardIterator __last);
template <class _InputIterator>
void __assign_multi(_InputIterator __first, _InputIterator __last);
#ifndef _LIBCPP_CXX03_LANG
#endif // !_LIBCPP_CXX03_LANG
_LIBCPP_INLINE_VISIBILITY
- pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
- _LIBCPP_INLINE_VISIBILITY
- iterator __node_insert_unique(const_iterator __p,
- __node_pointer __nd);
+ pair<iterator, bool> __node_assign_unique(const __container_value_type& __v, __node_pointer __dest);
_LIBCPP_INLINE_VISIBILITY
iterator __node_insert_multi(__node_pointer __nd);
_LIBCPP_INLINE_VISIBILITY
void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {}
- __node_pointer __detach();
- static __node_pointer __detach(__node_pointer);
+ struct _DetachedTreeCache {
+ _LIBCPP_INLINE_VISIBILITY
+ explicit _DetachedTreeCache(__tree *__t) _NOEXCEPT : __t_(__t),
+ __cache_root_(__detach_from_tree(__t)) {
+ __advance();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ __node_pointer __get() const _NOEXCEPT {
+ return __cache_elem_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __advance() _NOEXCEPT {
+ __cache_elem_ = __cache_root_;
+ if (__cache_root_) {
+ __cache_root_ = __detach_next(__cache_root_);
+ }
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ ~_DetachedTreeCache() {
+ __t_->destroy(__cache_elem_);
+ if (__cache_root_) {
+ while (__cache_root_->__parent_ != nullptr)
+ __cache_root_ = static_cast<__node_pointer>(__cache_root_->__parent_);
+ __t_->destroy(__cache_root_);
+ }
+ }
+
+ _DetachedTreeCache(_DetachedTreeCache const&) = delete;
+ _DetachedTreeCache& operator=(_DetachedTreeCache const&) = delete;
+
+ private:
+ _LIBCPP_INLINE_VISIBILITY
+ static __node_pointer __detach_from_tree(__tree *__t) _NOEXCEPT;
+ _LIBCPP_INLINE_VISIBILITY
+ static __node_pointer __detach_next(__node_pointer) _NOEXCEPT;
+
+ __tree *__t_;
+ __node_pointer __cache_root_;
+ __node_pointer __cache_elem_;
+ };
+
template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS map;
template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS multimap;
// Precondition: size() != 0
template <class _Tp, class _Compare, class _Allocator>
typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
-__tree<_Tp, _Compare, _Allocator>::__detach()
+__tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_from_tree(__tree *__t) _NOEXCEPT
{
- __node_pointer __cache = static_cast<__node_pointer>(__begin_node());
- __begin_node() = __end_node();
- __end_node()->__left_->__parent_ = nullptr;
- __end_node()->__left_ = nullptr;
- size() = 0;
+ __node_pointer __cache = static_cast<__node_pointer>(__t->__begin_node());
+ __t->__begin_node() = __t->__end_node();
+ __t->__end_node()->__left_->__parent_ = nullptr;
+ __t->__end_node()->__left_ = nullptr;
+ __t->size() = 0;
// __cache->__left_ == nullptr
if (__cache->__right_ != nullptr)
__cache = static_cast<__node_pointer>(__cache->__right_);
// This is no longer a red-black tree
template <class _Tp, class _Compare, class _Allocator>
typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
-__tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache)
+__tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_next(__node_pointer __cache) _NOEXCEPT
{
if (__cache->__parent_ == nullptr)
return nullptr;
}
template <class _Tp, class _Compare, class _Allocator>
-template <class _InputIterator>
+template <class _ForwardIterator>
void
-__tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last)
+__tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first, _ForwardIterator __last)
{
- typedef iterator_traits<_InputIterator> _ITraits;
+ typedef iterator_traits<_ForwardIterator> _ITraits;
typedef typename _ITraits::value_type _ItValueType;
static_assert((is_same<_ItValueType, __container_value_type>::value),
"__assign_unique may only be called with the containers value type");
-
+ static_assert(__is_forward_iterator<_ForwardIterator>::value,
+ "__assign_unique requires a forward iterator");
if (size() != 0)
{
- __node_pointer __cache = __detach();
-#ifndef _LIBCPP_NO_EXCEPTIONS
- try
- {
-#endif // _LIBCPP_NO_EXCEPTIONS
- for (; __cache != nullptr && __first != __last; ++__first)
- {
- __cache->__value_ = *__first;
- __node_pointer __next = __detach(__cache);
- __node_insert_unique(__cache);
- __cache = __next;
+ _DetachedTreeCache __cache(this);
+ for (; __cache.__get() != nullptr && __first != __last; ++__first) {
+ if (__node_assign_unique(*__first, __cache.__get()).second)
+ __cache.__advance();
}
-#ifndef _LIBCPP_NO_EXCEPTIONS
- }
- catch (...)
- {
- while (__cache->__parent_ != nullptr)
- __cache = static_cast<__node_pointer>(__cache->__parent_);
- destroy(__cache);
- throw;
- }
-#endif // _LIBCPP_NO_EXCEPTIONS
- if (__cache != nullptr)
- {
- while (__cache->__parent_ != nullptr)
- __cache = static_cast<__node_pointer>(__cache->__parent_);
- destroy(__cache);
- }
}
for (; __first != __last; ++__first)
__insert_unique(*__first);
" or the nodes value type");
if (size() != 0)
{
- __node_pointer __cache = __detach();
-#ifndef _LIBCPP_NO_EXCEPTIONS
- try
- {
-#endif // _LIBCPP_NO_EXCEPTIONS
- for (; __cache != nullptr && __first != __last; ++__first)
- {
- __cache->__value_ = *__first;
- __node_pointer __next = __detach(__cache);
- __node_insert_multi(__cache);
- __cache = __next;
- }
-#ifndef _LIBCPP_NO_EXCEPTIONS
- }
- catch (...)
- {
- while (__cache->__parent_ != nullptr)
- __cache = static_cast<__node_pointer>(__cache->__parent_);
- destroy(__cache);
- throw;
- }
-#endif // _LIBCPP_NO_EXCEPTIONS
- if (__cache != nullptr)
- {
- while (__cache->__parent_ != nullptr)
- __cache = static_cast<__node_pointer>(__cache->__parent_);
- destroy(__cache);
+ _DetachedTreeCache __cache(this);
+ for (; __cache.__get() && __first != __last; ++__first) {
+ __cache.__get()->__value_ = *__first;
+ __node_insert_multi(__cache.__get());
+ __cache.__advance();
}
}
for (; __first != __last; ++__first)
const_iterator __e = end();
if (size() != 0)
{
- __node_pointer __cache = __detach();
-#ifndef _LIBCPP_NO_EXCEPTIONS
- try
- {
-#endif // _LIBCPP_NO_EXCEPTIONS
- while (__cache != nullptr && __t.size() != 0)
- {
- __cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_);
- __node_pointer __next = __detach(__cache);
- __node_insert_multi(__cache);
- __cache = __next;
- }
-#ifndef _LIBCPP_NO_EXCEPTIONS
- }
- catch (...)
- {
- while (__cache->__parent_ != nullptr)
- __cache = static_cast<__node_pointer>(__cache->__parent_);
- destroy(__cache);
- throw;
- }
-#endif // _LIBCPP_NO_EXCEPTIONS
- if (__cache != nullptr)
- {
- while (__cache->__parent_ != nullptr)
- __cache = static_cast<__node_pointer>(__cache->__parent_);
- destroy(__cache);
+ _DetachedTreeCache __cache(this);
+ while (__cache.__get() != nullptr && __t.size() != 0) {
+ __cache.__get()->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_);
+ __node_insert_multi(__cache.__get());
+ __cache.__advance();
}
}
while (__t.size() != 0)
template <class _Tp, class _Compare, class _Allocator>
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
-__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd)
+__tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const __container_value_type& __v, __node_pointer __nd)
{
__parent_pointer __parent;
- __node_base_pointer& __child = __find_equal(__parent, __nd->__value_);
+ __node_base_pointer& __child = __find_equal(__parent, _NodeTypes::__get_key(__v));
__node_pointer __r = static_cast<__node_pointer>(__child);
bool __inserted = false;
if (__child == nullptr)
{
+ __nd->__value_ = __v;
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
__r = __nd;
__inserted = true;
return pair<iterator, bool>(iterator(__r), __inserted);
}
-template <class _Tp, class _Compare, class _Allocator>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p,
- __node_pointer __nd)
-{
- __parent_pointer __parent;
- __node_base_pointer __dummy;
- __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_);
- __node_pointer __r = static_cast<__node_pointer>(__child);
- if (__child == nullptr)
- {
- __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
- __r = __nd;
- }
- return iterator(__r);
-}
template <class _Tp, class _Compare, class _Allocator>
typename __tree<_Tp, _Compare, _Allocator>::iterator