diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp index 4e5c2dbb..9ee1343c 100644 --- a/include/boost/unordered/detail/buckets.hpp +++ b/include/boost/unordered/detail/buckets.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #if defined(BOOST_MSVC) #pragma warning(push) @@ -32,6 +33,8 @@ namespace boost { namespace unordered { namespace detail { struct ptr_bucket; template struct buckets; + template struct table_impl; + template struct grouped_table_impl; /////////////////////////////////////////////////////////////////// // @@ -180,6 +183,272 @@ namespace boost { namespace unordered { namespace detail { enum { extra_node = false }; }; +}}} + +namespace boost { namespace unordered { namespace iterator_detail { + + //////////////////////////////////////////////////////////////////////////// + // Iterators + // + // all no throw + + template struct iterator; + template struct c_iterator; + template + struct l_iterator; + template struct cl_iterator; + + // Local Iterators + // + // all no throw + + template + struct l_iterator + : public boost::iterator< + std::forward_iterator_tag, Value, std::ptrdiff_t, + NodePointer, Value&> + { +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template + friend struct boost::unordered::iterator_detail::cl_iterator; + private: +#endif + typedef NodePointer node_pointer; + typedef boost::unordered::iterator_detail::iterator + iterator; + node_pointer ptr_; + std::size_t bucket_; + std::size_t bucket_count_; + + public: + + l_iterator() : ptr_() {} + + l_iterator(iterator x, std::size_t b, std::size_t c) + : ptr_(x.node_), bucket_(b), bucket_count_(c) {} + + Value& operator*() const { + return ptr_->value(); + } + + Value* operator->() const { + return ptr_->value_ptr(); + } + + l_iterator& operator++() { + ptr_ = static_cast(ptr_->next_); + if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) + != bucket_) + ptr_ = node_pointer(); + return *this; + } + + l_iterator operator++(int) { + l_iterator tmp(*this); + ++(*this); + return tmp; + } + + bool operator==(l_iterator x) const { + return ptr_ == x.ptr_; + } + + bool operator!=(l_iterator x) const { + return ptr_ != x.ptr_; + } + }; + + template + struct cl_iterator + : public boost::iterator< + std::forward_iterator_tag, Value, std::ptrdiff_t, + ConstNodePointer, Value const&> + { + friend struct boost::unordered::iterator_detail::l_iterator + ; + private: + + typedef NodePointer node_pointer; + typedef boost::unordered::iterator_detail::iterator + iterator; + node_pointer ptr_; + std::size_t bucket_; + std::size_t bucket_count_; + + public: + + cl_iterator() : ptr_() {} + + cl_iterator(iterator x, std::size_t b, std::size_t c) : + ptr_(x.node_), bucket_(b), bucket_count_(c) {} + + cl_iterator(boost::unordered::iterator_detail::l_iterator< + NodePointer, Value, Policy> const& x) : + ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_) + {} + + Value const& + operator*() const { + return ptr_->value(); + } + + Value const* operator->() const { + return ptr_->value_ptr(); + } + + cl_iterator& operator++() { + ptr_ = static_cast(ptr_->next_); + if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) + != bucket_) + ptr_ = node_pointer(); + return *this; + } + + cl_iterator operator++(int) { + cl_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(cl_iterator const& x, cl_iterator const& y) { + return x.ptr_ == y.ptr_; + } + + friend bool operator!=(cl_iterator const& x, cl_iterator const& y) { + return x.ptr_ != y.ptr_; + } + }; + + template + struct iterator + : public boost::iterator< + std::forward_iterator_tag, Value, std::ptrdiff_t, + NodePointer, Value&> + { +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template + friend struct boost::unordered::iterator_detail::c_iterator; + template + friend struct boost::unordered::iterator_detail::l_iterator; + template + friend struct boost::unordered::iterator_detail::cl_iterator; + template + friend struct boost::unordered::detail::table; + template + friend struct boost::unordered::detail::buckets; + template + friend struct boost::unordered::detail::table_impl; + template + friend struct boost::unordered::detail::grouped_table_impl; + private: +#endif + typedef NodePointer node_pointer; + node_pointer node_; + + public: + + iterator() : node_() {} + + explicit iterator(node_pointer const& x) : node_(x) {} + + Value& operator*() const { + return node_->value(); + } + + Value* operator->() const { + return &node_->value(); + } + + iterator& operator++() { + node_ = static_cast(node_->next_); + return *this; + } + + iterator operator++(int) { + iterator tmp(node_); + node_ = static_cast(node_->next_); + return tmp; + } + + bool operator==(iterator const& x) const { + return node_ == x.node_; + } + + bool operator!=(iterator const& x) const { + return node_ != x.node_; + } + }; + + template + struct c_iterator + : public boost::iterator< + std::forward_iterator_tag, Value, std::ptrdiff_t, + ConstNodePointer, Value const&> + { + friend struct boost::unordered::iterator_detail::iterator< + NodePointer, Value>; + +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template + friend struct boost::unordered::detail::table; + template + friend struct boost::unordered::detail::buckets; + template + friend struct boost::unordered::detail::table_impl; + template + friend struct boost::unordered::detail::grouped_table_impl; + + private: +#endif + + typedef NodePointer node_pointer; + typedef boost::unordered::iterator_detail::iterator + iterator; + node_pointer node_; + + public: + + c_iterator() : node_() {} + + explicit c_iterator(node_pointer const& x) : node_(x) {} + + c_iterator(boost::unordered::iterator_detail::iterator< + NodePointer, Value> const& x) : node_(x.node_) {} + + Value const& operator*() const { + return node_->value(); + } + + Value const* operator->() const { + return &node_->value(); + } + + c_iterator& operator++() { + node_ = static_cast(node_->next_); + return *this; + } + + c_iterator operator++(int) { + c_iterator tmp(node_); + node_ = static_cast(node_->next_); + return tmp; + } + + friend bool operator==(c_iterator const& x, c_iterator const& y) { + return x.node_ == y.node_; + } + + friend bool operator!=(c_iterator const& x, c_iterator const& y) { + return x.node_ != y.node_; + } + }; +}}} + +namespace boost { namespace unordered { namespace detail { /////////////////////////////////////////////////////////////////// // @@ -302,6 +571,16 @@ namespace boost { namespace unordered { namespace detail { typedef boost::unordered::detail::node_constructor node_constructor; + typedef boost::unordered::iterator_detail:: + iterator iterator; + typedef boost::unordered::iterator_detail:: + c_iterator c_iterator; + typedef boost::unordered::iterator_detail:: + l_iterator l_iterator; + typedef boost::unordered::iterator_detail:: + cl_iterator + cl_iterator; + // Members bucket_pointer buckets_; @@ -354,16 +633,17 @@ namespace boost { namespace unordered { namespace detail { return this->get_bucket(bucket_index)->next_; } - node_pointer get_start() const + iterator get_start() const { - return static_cast(this->get_previous_start()->next_); + return iterator(static_cast( + this->get_previous_start()->next_)); } - node_pointer get_start(std::size_t bucket_index) const + iterator get_start(std::size_t bucket_index) const { previous_pointer prev = this->get_previous_start(bucket_index); - return prev ? static_cast(prev->next_) : - node_pointer(); + return prev ? iterator(static_cast(prev->next_)) : + iterator(); } float load_factor() const @@ -376,15 +656,15 @@ namespace boost { namespace unordered { namespace detail { std::size_t bucket_size(std::size_t index) const { if (!this->size_) return 0; - node_pointer ptr = this->get_start(index); - if (!ptr) return 0; + iterator it = this->get_start(index); + if (!it.node_) return 0; std::size_t count = 0; - while(ptr && - policy::to_bucket(this->bucket_count_, ptr->hash_) == index) + while(it.node_ && policy::to_bucket( + this->bucket_count_, it.node_->hash_) == index) { ++count; - ptr = static_cast(ptr->next_); + ++it; } return count; @@ -480,21 +760,22 @@ namespace boost { namespace unordered { namespace detail { //////////////////////////////////////////////////////////////////////// // Delete/destruct - inline void delete_node(node_pointer n) + inline void delete_node(c_iterator n) { - boost::unordered::detail::destroy(n->value_ptr()); - node_allocator_traits::destroy(node_alloc(), boost::addressof(*n)); - node_allocator_traits::deallocate(node_alloc(), n, 1); + boost::unordered::detail::destroy(n.node_->value_ptr()); + node_allocator_traits::destroy(node_alloc(), + boost::addressof(*n.node_)); + node_allocator_traits::deallocate(node_alloc(), n.node_, 1); --size_; } - std::size_t delete_nodes(node_pointer begin, node_pointer end) + std::size_t delete_nodes(c_iterator begin, c_iterator end) { std::size_t count = 0; while(begin != end) { - node_pointer n = begin; - begin = static_cast(begin->next_); + c_iterator n = begin; + ++begin; delete_node(n); ++count; } @@ -522,7 +803,7 @@ namespace boost { namespace unordered { namespace detail { while(prev->next_) { node_pointer n = static_cast(prev->next_); prev->next_ = n->next_; - delete_node(n); + delete_node(iterator(n)); } delete_extra_node(prev); @@ -552,7 +833,7 @@ namespace boost { namespace unordered { namespace detail { while(prev->next_) { node_pointer n = static_cast(prev->next_); prev->next_ = n->next_; - delete_node(n); + delete_node(iterator(n)); } bucket_pointer end = this->get_bucket(this->bucket_count_); diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp index 8448cc33..ba58c8a2 100644 --- a/include/boost/unordered/detail/equivalent.hpp +++ b/include/boost/unordered/detail/equivalent.hpp @@ -186,6 +186,7 @@ namespace boost { namespace unordered { namespace detail { typedef typename table::node_constructor node_constructor; typedef typename table::extractor extractor; typedef typename table::iterator iterator; + typedef typename table::c_iterator c_iterator; // Constructors @@ -219,48 +220,48 @@ namespace boost { namespace unordered { namespace detail { // Accessors template - node_pointer find_node_impl( + iterator find_node_impl( std::size_t hash, Key const& k, Pred const& eq) const { std::size_t bucket_index = policy::to_bucket(this->bucket_count_, hash); - node_pointer n = this->get_start(bucket_index); + iterator n = this->get_start(bucket_index); for (;;) { - if (!n) return n; + if (!n.node_) return n; - std::size_t node_hash = n->hash_; + std::size_t node_hash = n.node_->hash_; if (hash == node_hash) { - if (eq(k, this->get_key(n->value()))) + if (eq(k, this->get_key(*n))) return n; } else { if (policy::to_bucket(this->bucket_count_, node_hash) != bucket_index) - return node_pointer(); + return iterator(); } - n = static_cast( - static_cast(n->group_prev_)->next_); + n = iterator(static_cast( + static_cast(n.node_->group_prev_)->next_)); } } std::size_t count(key_type const& k) const { - node_pointer n = this->find_node(k); - if (!n) return 0; + iterator n = this->find_node(k); + if (!n.node_) return 0; std::size_t count = 0; - node_pointer it = n; + node_pointer it = n.node_; do { it = static_cast(it->group_prev_); ++count; - } while(it != n); + } while(it != n.node_); return count; } @@ -268,12 +269,12 @@ namespace boost { namespace unordered { namespace detail { std::pair equal_range(key_type const& k) const { - node_pointer n = this->find_node(k); + iterator n = this->find_node(k); return std::make_pair( - iterator(n), iterator(n ? + n, n.node_ ? iterator( static_cast( - static_cast(n->group_prev_)->next_) : - n)); + static_cast(n.node_->group_prev_)->next_ + )) : n); } // Equality @@ -283,14 +284,14 @@ namespace boost { namespace unordered { namespace detail { if(this->size_ != other.size_) return false; if(!this->size_) return true; - for(node_pointer n1 = this->get_start(); n1;) + for(iterator n1 = this->get_start(); n1.node_;) { - node_pointer n2 = other.find_matching_node(n1); - if (!n2) return false; - node_pointer end1 = static_cast( - static_cast(n1->group_prev_)->next_); - node_pointer end2 = static_cast( - static_cast(n2->group_prev_)->next_); + iterator n2 = other.find_matching_node(n1); + if (!n2.node_) return false; + iterator end1(static_cast( + static_cast(n1.node_->group_prev_)->next_)); + iterator end2(static_cast( + static_cast(n2.node_->group_prev_)->next_)); if (!group_equals(n1, end1, n2, end2)) return false; n1 = end1; } @@ -300,25 +301,24 @@ namespace boost { namespace unordered { namespace detail { #if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY) - static bool group_equals(node_pointer n1, node_pointer end1, - node_pointer n2, node_pointer end2) + static bool group_equals(iterator n1, iterator end1, + iterator n2, iterator end2) { for(;;) { - if (n1->value() != n2->value()) - break; + if (*n1 != *n2) break; - n1 = static_cast(n1->next_); - n2 = static_cast(n2->next_); + ++n1; + ++n2; if (n1 == end1) return n2 == end2; if (n2 == end2) return false; } - for(node_pointer n1a = n1, n2a = n2;;) + for(iterator n1a = n1, n2a = n2;;) { - n1a = static_cast(n1a->next_); - n2a = static_cast(n2a->next_); + ++n1a; + ++n2a; if (n1a == end1) { @@ -329,50 +329,50 @@ namespace boost { namespace unordered { namespace detail { if (n2a == end2) return false; } - node_pointer start = n1; - for(;n1 != end1; n1 = static_cast(n1->next_)) + iterator start = n1; + for(;n1 != end1; ++n1) { - value_type const& v = n1->value(); + value_type const& v = *n1; if (find(start, n1, v)) continue; std::size_t matches = count_equal(n2, end2, v); - if (!matches || matches != 1 + count_equal( - static_cast(n1->next_), end1, v)) - return false; + if (!matches) return false; + iterator next = n1; + ++next; + if (matches != 1 + count_equal(next, end1, v)) return false; } return true; } - static bool find(node_pointer n, node_pointer end, value_type const& v) + static bool find(iterator n, iterator end, value_type const& v) { - for(;n != end; n = static_cast(n->next_)) - if (n->value() == v) + for(;n != end; ++n) + if (*n == v) return true; return false; } - static std::size_t count_equal(node_pointer n, node_pointer end, + static std::size_t count_equal(iterator n, iterator end, value_type const& v) { std::size_t count = 0; - for(;n != end; n = static_cast(n->next_)) - if (n->value() == v) ++count; + for(;n != end; ++n) + if (*n == v) ++count; return count; } #else - static bool group_equals(node_pointer n1, node_pointer end1, - node_pointer n2, node_pointer end2) + static bool group_equals(iterator n1, iterator end1, + iterator n2, iterator end2) { for(;;) { - if(!extractor::compare_mapped( - n1->value(), n2->value())) + if(!extractor::compare_mapped(*n1, *n2)) return false; - n1 = static_cast(n1->next_); - n2 = static_cast(n2->next_); + ++n1; + ++n2; if (n1 == end1) return n2 == end2; if (n2 == end2) return false; @@ -394,15 +394,15 @@ namespace boost { namespace unordered { namespace detail { pos->group_prev_ = static_cast(n); } - inline node_pointer add_node( + inline iterator add_node( node_constructor& a, std::size_t hash, - node_pointer pos) + iterator pos) { node_pointer n = a.release(); n->hash_ = hash; - if(pos) { - this->add_after_node(n, pos); + if (pos.node_) { + this->add_after_node(n, pos.node_); if (n->next_) { std::size_t next_bucket = policy::to_bucket( this->bucket_count_, @@ -438,14 +438,14 @@ namespace boost { namespace unordered { namespace detail { } } ++this->size_; - return n; + return iterator(n); } - node_pointer emplace_impl(node_constructor& a) + iterator emplace_impl(node_constructor& a) { key_type const& k = this->get_key(a.value()); std::size_t hash = this->hash(k); - node_pointer position = this->find_node(hash, k); + iterator position = this->find_node(hash, k); // reserve has basic exception safety if the hash function // throws, strong otherwise. @@ -457,8 +457,7 @@ namespace boost { namespace unordered { namespace detail { { key_type const& k = this->get_key(a.value()); std::size_t hash = this->hash(k); - this->add_node(a, hash, - this->find_node(hash, k)); + this->add_node(a, hash, this->find_node(hash, k)); } #if defined(BOOST_NO_RVALUE_REFERENCES) @@ -562,37 +561,38 @@ namespace boost { namespace unordered { namespace detail { node_pointer end = static_cast(end1); prev->next_ = end1; this->fix_buckets(bucket, prev, end); - return this->delete_nodes(pos, end); + return this->delete_nodes(c_iterator(pos), c_iterator(end)); } - node_pointer erase(node_pointer r) + iterator erase(c_iterator r) { - BOOST_ASSERT(r); - node_pointer next = static_cast(r->next_); + BOOST_ASSERT(r.node_); + iterator next(r.node_); + ++next; bucket_pointer bucket = this->get_bucket( - policy::to_bucket(this->bucket_count_, r->hash_)); - previous_pointer prev = unlink_node(*bucket, r); + policy::to_bucket(this->bucket_count_, r.node_->hash_)); + previous_pointer prev = unlink_node(*bucket, r.node_); - this->fix_buckets(bucket, prev, next); + this->fix_buckets(bucket, prev, next.node_); this->delete_node(r); return next; } - node_pointer erase_range(node_pointer r1, node_pointer r2) + iterator erase_range(c_iterator r1, c_iterator r2) { - if (r1 == r2) return r2; + if (r1 == r2) return iterator(r2.node_); std::size_t bucket_index = - policy::to_bucket(this->bucket_count_, r1->hash_); + policy::to_bucket(this->bucket_count_, r1.node_->hash_); previous_pointer prev = unlink_nodes( - *this->get_bucket(bucket_index), r1, r2); - this->fix_buckets_range(bucket_index, prev, r1, r2); + *this->get_bucket(bucket_index), r1.node_, r2.node_); + this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_); this->delete_nodes(r1, r2); - return r2; + return iterator(r2.node_); } static previous_pointer unlink_node(bucket& b, node_pointer n) @@ -709,17 +709,18 @@ namespace boost { namespace unordered { namespace detail { node_constructor a(dst.node_alloc()); - node_pointer n = src.get_start(); + iterator n = src.get_start(); previous_pointer prev = dst.get_previous_start(); - while(n) { - std::size_t hash = n->hash_; - node_pointer group_end = + while (n.node_) { + std::size_t hash = n.node_->hash_; + iterator group_end( static_cast( - static_cast(n->group_prev_)->next_); + static_cast(n.node_->group_prev_)->next_ + )); a.construct_node(); - a.construct_value2(n->value()); + a.construct_value2(*n); node_pointer first_node = a.release(); node_pointer end = first_node; @@ -727,11 +728,10 @@ namespace boost { namespace unordered { namespace detail { prev->next_ = static_cast(first_node); ++dst.size_; - for(n = static_cast(n->next_); n != group_end; - n = static_cast(n->next_)) + for (++n; n != group_end; ++n) { a.construct_node(); - a.construct_value2(n->value()); + a.construct_value2(*n); end = a.release(); end->hash_ = hash; add_after_node(end, first_node); @@ -756,17 +756,18 @@ namespace boost { namespace unordered { namespace detail { node_constructor a(dst.node_alloc()); - node_pointer n = src.get_start(); + iterator n = src.get_start(); previous_pointer prev = dst.get_previous_start(); - while(n) { - std::size_t hash = n->hash_; - node_pointer group_end = + while (n.node_) { + std::size_t hash = n.node_->hash_; + iterator group_end( static_cast( - static_cast(n->group_prev_)->next_); + static_cast(n.node_->group_prev_)->next_ + )); a.construct_node(); - a.construct_value2(boost::move(n->value())); + a.construct_value2(boost::move(*n)); node_pointer first_node = a.release(); node_pointer end = first_node; @@ -774,11 +775,10 @@ namespace boost { namespace unordered { namespace detail { prev->next_ = static_cast(first_node); ++dst.size_; - for(n = static_cast(n->next_); n != group_end; - n = static_cast(n->next_)) + for(++n; n != group_end; ++n) { a.construct_node(); - a.construct_value2(boost::move(n->value())); + a.construct_value2(boost::move(*n)); end = a.release(); end->hash_ = hash; add_after_node(end, first_node); diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 638f84bd..9e2f13c5 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -11,255 +11,8 @@ #include #include #include -#include #include -namespace boost { namespace unordered { namespace iterator_detail { - - //////////////////////////////////////////////////////////////////////////// - // Iterators - // - // all no throw - - template struct iterator; - template struct c_iterator; - template - struct l_iterator; - template struct cl_iterator; - - // Local Iterators - // - // all no throw - - template - struct l_iterator - : public boost::iterator< - std::forward_iterator_tag, Value, std::ptrdiff_t, - NodePointer, Value&> - { -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template - friend struct boost::unordered::iterator_detail::cl_iterator; - private: -#endif - typedef NodePointer node_pointer; - node_pointer ptr_; - std::size_t bucket_; - std::size_t bucket_count_; - - public: - - l_iterator() : ptr_() {} - - l_iterator(node_pointer x, std::size_t b, std::size_t c) - : ptr_(x), bucket_(b), bucket_count_(c) {} - - Value& operator*() const { - return ptr_->value(); - } - - Value* operator->() const { - return ptr_->value_ptr(); - } - - l_iterator& operator++() { - ptr_ = static_cast(ptr_->next_); - if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) - != bucket_) - ptr_ = node_pointer(); - return *this; - } - - l_iterator operator++(int) { - l_iterator tmp(*this); - ++(*this); - return tmp; - } - - bool operator==(l_iterator x) const { - return ptr_ == x.ptr_; - } - - bool operator!=(l_iterator x) const { - return ptr_ != x.ptr_; - } - }; - - template - struct cl_iterator - : public boost::iterator< - std::forward_iterator_tag, Value, std::ptrdiff_t, - ConstNodePointer, Value const&> - { - friend struct boost::unordered::iterator_detail::l_iterator - ; - private: - - typedef NodePointer node_pointer; - node_pointer ptr_; - std::size_t bucket_; - std::size_t bucket_count_; - - public: - - cl_iterator() : ptr_() {} - - cl_iterator(node_pointer x, std::size_t b, std::size_t c) : - ptr_(x), bucket_(b), bucket_count_(c) {} - - cl_iterator(boost::unordered::iterator_detail::l_iterator< - NodePointer, Value, Policy> const& x) : - ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_) - {} - - Value const& - operator*() const { - return ptr_->value(); - } - - Value const* operator->() const { - return ptr_->value_ptr(); - } - - cl_iterator& operator++() { - ptr_ = static_cast(ptr_->next_); - if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) - != bucket_) - ptr_ = node_pointer(); - return *this; - } - - cl_iterator operator++(int) { - cl_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(cl_iterator const& x, cl_iterator const& y) { - return x.ptr_ == y.ptr_; - } - - friend bool operator!=(cl_iterator const& x, cl_iterator const& y) { - return x.ptr_ != y.ptr_; - } - }; - - template - struct iterator - : public boost::iterator< - std::forward_iterator_tag, Value, std::ptrdiff_t, - NodePointer, Value&> - { -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template - friend struct boost::unordered::iterator_detail::c_iterator; - private: -#endif - typedef NodePointer node_pointer; - node_pointer node_; - - public: - - iterator() : node_() {} - - explicit iterator(node_pointer const& x) : node_(x) {} - - Value& operator*() const { - return node_->value(); - } - - Value* operator->() const { - return &node_->value(); - } - - iterator& operator++() { - node_ = static_cast(node_->next_); - return *this; - } - - iterator operator++(int) { - iterator tmp(node_); - node_ = static_cast(node_->next_); - return tmp; - } - - bool operator==(iterator const& x) const { - return node_ == x.node_; - } - - bool operator!=(iterator const& x) const { - return node_ != x.node_; - } - }; - - template - struct c_iterator - : public boost::iterator< - std::forward_iterator_tag, Value, std::ptrdiff_t, - ConstNodePointer, Value const&> - { - friend struct boost::unordered::iterator_detail::iterator< - NodePointer, Value>; - -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template - friend class boost::unordered::unordered_map; - template - friend class boost::unordered::unordered_multimap; - template - friend class boost::unordered::unordered_set; - template - friend class boost::unordered::unordered_multiset; - - private: -#endif - - typedef NodePointer node_pointer; - node_pointer node_; - - public: - - c_iterator() : node_() {} - - explicit c_iterator(node_pointer const& x) : node_(x) {} - - c_iterator(boost::unordered::iterator_detail::iterator< - NodePointer, Value> const& x) : node_(x.node_) {} - - Value const& operator*() const { - return node_->value(); - } - - Value const* operator->() const { - return &node_->value(); - } - - c_iterator& operator++() { - node_ = static_cast(node_->next_); - return *this; - } - - c_iterator operator++(int) { - c_iterator tmp(node_); - node_ = static_cast(node_->next_); - return tmp; - } - - friend bool operator==(c_iterator const& x, c_iterator const& y) { - return x.node_ == y.node_; - } - - friend bool operator!=(c_iterator const& x, c_iterator const& y) { - return x.node_ != y.node_; - } - }; -}}} - namespace boost { namespace unordered { namespace detail { //////////////////////////////////////////////////////////////////////////// @@ -340,15 +93,7 @@ namespace boost { namespace unordered { namespace detail { typedef typename buckets::node_pointer node_pointer; typedef typename buckets::const_node_pointer const_node_pointer; - typedef boost::unordered::iterator_detail:: - iterator iterator; - typedef boost::unordered::iterator_detail:: - c_iterator c_iterator; - typedef boost::unordered::iterator_detail:: - l_iterator l_iterator; - typedef boost::unordered::iterator_detail:: - cl_iterator - cl_iterator; + typedef typename table::iterator iterator; // Members @@ -465,9 +210,9 @@ namespace boost { namespace unordered { namespace detail { // Iterators - node_pointer begin() const { + iterator begin() const { return !this->buckets_ ? - node_pointer() : this->get_start(); + iterator() : this->get_start(); } // Assignment @@ -601,33 +346,33 @@ namespace boost { namespace unordered { namespace detail { // Find Node template - node_pointer generic_find_node( + iterator generic_find_node( Key const& k, Hash const& hash_function, Pred const& eq) const { - if (!this->size_) return node_pointer(); + if (!this->size_) return iterator(); return static_cast(this)-> find_node_impl(policy::apply_hash(hash_function, k), k, eq); } - node_pointer find_node( + iterator find_node( std::size_t hash, key_type const& k) const { - if (!this->size_) return node_pointer(); + if (!this->size_) return iterator(); return static_cast(this)-> find_node_impl(hash, k, this->key_eq()); } - node_pointer find_node(key_type const& k) const + iterator find_node(key_type const& k) const { - if (!this->size_) return node_pointer(); + if (!this->size_) return iterator(); return static_cast(this)-> find_node_impl(this->hash(k), k, this->key_eq()); } - node_pointer find_matching_node(node_pointer n) const + iterator find_matching_node(iterator n) const { // TODO: Does this apply to C++11? // @@ -635,7 +380,7 @@ namespace boost { namespace unordered { namespace detail { // when different hash functions are used. So I can't use the hash // value from the node here. - return find_node(get_key(n->value())); + return find_node(get_key(*n)); } // Reserve and rehash diff --git a/include/boost/unordered/detail/unique.hpp b/include/boost/unordered/detail/unique.hpp index 06bfaa36..84fef433 100644 --- a/include/boost/unordered/detail/unique.hpp +++ b/include/boost/unordered/detail/unique.hpp @@ -182,6 +182,7 @@ namespace boost { namespace unordered { namespace detail { typedef typename table::node_constructor node_constructor; typedef typename table::extractor extractor; typedef typename table::iterator iterator; + typedef typename table::c_iterator c_iterator; typedef std::pair emplace_return; @@ -217,46 +218,46 @@ namespace boost { namespace unordered { namespace detail { // Accessors template - node_pointer find_node_impl( + iterator find_node_impl( std::size_t hash, Key const& k, Pred const& eq) const { std::size_t bucket_index = policy::to_bucket(this->bucket_count_, hash); - node_pointer n = this->get_start(bucket_index); + iterator n = this->get_start(bucket_index); for (;;) { - if (!n) return n; + if (!n.node_) return n; - std::size_t node_hash = n->hash_; + std::size_t node_hash = n.node_->hash_; if (hash == node_hash) { - if (eq(k, this->get_key(n->value()))) + if (eq(k, this->get_key(*n))) return n; } else { if (policy::to_bucket(this->bucket_count_, node_hash) != bucket_index) - return node_pointer(); + return iterator(); } - n = static_cast(n->next_); + ++n; } } std::size_t count(key_type const& k) const { - return this->find_node(k) ? 1 : 0; + return this->find_node(k).node_ ? 1 : 0; } value_type& at(key_type const& k) const { if (this->size_) { - node_pointer it = this->find_node(k); - if (it) return it->value(); + iterator it = this->find_node(k); + if (it.node_) return *it; } boost::throw_exception( @@ -266,9 +267,10 @@ namespace boost { namespace unordered { namespace detail { std::pair equal_range(key_type const& k) const { - node_pointer n = this->find_node(k); - return std::make_pair(iterator(n), - iterator(n ? static_cast(n->next_) : n)); + iterator n = this->find_node(k); + iterator n2 = n; + if (n2.node_) ++n2; + return std::make_pair(n, n2); } // equals @@ -278,17 +280,15 @@ namespace boost { namespace unordered { namespace detail { if(this->size_ != other.size_) return false; if(!this->size_) return true; - for(node_pointer n1 = this->get_start(); n1; - n1 = static_cast(n1->next_)) + for(iterator n1 = this->get_start(); n1.node_; ++n1) { - node_pointer n2 = other.find_matching_node(n1); + iterator n2 = other.find_matching_node(n1); #if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY) - if(!n2 || n1->value() != n2->value()) + if (!n2.node_ || *n1 != *n2) return false; #else - if(!n2 || !extractor::compare_mapped( - n1->value(), n2->value())) + if (!n2.node_ || !extractor::compare_mapped(*n1, *n2)) return false; #endif } @@ -298,7 +298,7 @@ namespace boost { namespace unordered { namespace detail { // Emplace/Insert - inline node_pointer add_node( + inline iterator add_node( node_constructor& a, std::size_t hash) { @@ -329,7 +329,7 @@ namespace boost { namespace unordered { namespace detail { } ++this->size_; - return n; + return iterator(n); } value_type& operator[](key_type const& k) @@ -337,9 +337,9 @@ namespace boost { namespace unordered { namespace detail { typedef typename value_type::second_type mapped_type; std::size_t hash = this->hash(k); - node_pointer pos = this->find_node(hash, k); + iterator pos = this->find_node(hash, k); - if (pos) return pos->value(); + if (pos.node_) return *pos; // Create the node before rehashing in case it throws an // exception (need strong safety in such a case). @@ -357,7 +357,7 @@ namespace boost { namespace unordered { namespace detail { #endif this->reserve_for_insert(this->size_ + 1); - return add_node(a, hash)->value(); + return *add_node(a, hash); } #if defined(BOOST_NO_RVALUE_REFERENCES) @@ -365,7 +365,7 @@ namespace boost { namespace unordered { namespace detail { boost::unordered::detail::please_ignore_this_overload> const&) { BOOST_ASSERT(false); - return emplace_return(iterator(this->begin()), false); + return emplace_return(this->begin(), false); } #endif @@ -398,9 +398,9 @@ namespace boost { namespace unordered { namespace detail { BOOST_UNORDERED_EMPLACE_ARGS) { std::size_t hash = this->hash(k); - node_pointer pos = this->find_node(hash, k); + iterator pos = this->find_node(hash, k); - if (pos) return emplace_return(iterator(pos), false); + if (pos.node_) return emplace_return(pos, false); // Create the node before rehashing in case it throws an // exception (need strong safety in such a case). @@ -411,21 +411,21 @@ namespace boost { namespace unordered { namespace detail { // reserve has basic exception safety if the hash function // throws, strong otherwise. this->reserve_for_insert(this->size_ + 1); - return emplace_return(iterator(this->add_node(a, hash)), true); + return emplace_return(this->add_node(a, hash), true); } emplace_return emplace_impl_with_node(node_constructor& a) { key_type const& k = this->get_key(a.value()); std::size_t hash = this->hash(k); - node_pointer pos = this->find_node(hash, k); + iterator pos = this->find_node(hash, k); - if (pos) return emplace_return(iterator(pos), false); + if (pos.node_) return emplace_return(pos, false); // reserve has basic exception safety if the hash function // throws, strong otherwise. this->reserve_for_insert(this->size_ + 1); - return emplace_return(iterator(this->add_node(a, hash)), true); + return emplace_return(this->add_node(a, hash), true); } template @@ -495,9 +495,9 @@ namespace boost { namespace unordered { namespace detail { { // No side effects in this initial code std::size_t hash = this->hash(k); - node_pointer pos = this->find_node(hash, k); + iterator pos = this->find_node(hash, k); - if (!pos) { + if (!pos.node_) { a.construct_node(); a.construct_value2(*i); @@ -558,37 +558,38 @@ namespace boost { namespace unordered { namespace detail { node_pointer end = static_cast(pos->next_); prev->next_ = pos->next_; this->fix_buckets(bucket, prev, end); - return this->delete_nodes(pos, end); + return this->delete_nodes(c_iterator(pos), c_iterator(end)); } - node_pointer erase(node_pointer r) + iterator erase(c_iterator r) { - BOOST_ASSERT(r); - node_pointer next = static_cast(r->next_); + BOOST_ASSERT(r.node_); + iterator next(r.node_); + ++next; bucket_pointer bucket = this->get_bucket( - policy::to_bucket(this->bucket_count_, r->hash_)); - previous_pointer prev = unlink_node(*bucket, r); + policy::to_bucket(this->bucket_count_, r.node_->hash_)); + previous_pointer prev = unlink_node(*bucket, r.node_); - this->fix_buckets(bucket, prev, next); + this->fix_buckets(bucket, prev, next.node_); this->delete_node(r); return next; } - node_pointer erase_range(node_pointer r1, node_pointer r2) + iterator erase_range(c_iterator r1, c_iterator r2) { - if (r1 == r2) return r2; + if (r1 == r2) return iterator(r2.node_); std::size_t bucket_index = - policy::to_bucket(this->bucket_count_, r1->hash_); + policy::to_bucket(this->bucket_count_, r1.node_->hash_); previous_pointer prev = unlink_nodes( - *this->get_bucket(bucket_index), r1, r2); - this->fix_buckets_range(bucket_index, prev, r1, r2); + *this->get_bucket(bucket_index), r1.node_, r2.node_); + this->fix_buckets_range(bucket_index, prev, r1.node_, r2.node_); this->delete_nodes(r1, r2); - return r2; + return iterator(r2.node_); } static previous_pointer unlink_node(bucket& b, node_pointer n) @@ -621,18 +622,18 @@ namespace boost { namespace unordered { namespace detail { node_constructor a(dst.node_alloc()); - node_pointer n = src.get_start(); + iterator n = src.get_start(); previous_pointer prev = dst.get_previous_start(); - while(n) { + while(n.node_) { a.construct_node(); - a.construct_value2(n->value()); + a.construct_value2(*n); node_pointer node = a.release(); - node->hash_ = n->hash_; + node->hash_ = n.node_->hash_; prev->next_ = static_cast(node); ++dst.size_; - n = static_cast(n->next_); + ++n; prev = place_in_bucket(dst, prev); } @@ -652,18 +653,18 @@ namespace boost { namespace unordered { namespace detail { node_constructor a(dst.node_alloc()); - node_pointer n = src.get_start(); + iterator n = src.get_start(); previous_pointer prev = dst.get_previous_start(); - while(n) { + while (n.node_) { a.construct_node(); - a.construct_value2(boost::move(n->value())); + a.construct_value2(boost::move(*n)); node_pointer node = a.release(); - node->hash_ = n->hash_; + node->hash_ = n.node_->hash_; prev->next_ = static_cast(node); ++dst.size_; - n = static_cast(n->next_); + ++n; prev = place_in_bucket(dst, prev); } diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 371d077d..7378b913 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -203,12 +203,12 @@ namespace unordered iterator begin() { - return iterator(table_.begin()); + return table_.begin(); } const_iterator begin() const { - return const_iterator(table_.begin()); + return table_.begin(); } iterator end() @@ -223,7 +223,7 @@ namespace unordered const_iterator cbegin() const { - return const_iterator(table_.begin()); + return table_.begin(); } const_iterator cend() const @@ -689,12 +689,12 @@ namespace unordered iterator begin() { - return iterator(table_.begin()); + return table_.begin(); } const_iterator begin() const { - return const_iterator(table_.begin()); + return table_.begin(); } iterator end() @@ -709,7 +709,7 @@ namespace unordered const_iterator cbegin() const { - return const_iterator(table_.begin()); + return table_.begin(); } const_iterator cend() const @@ -1141,7 +1141,7 @@ namespace unordered typename unordered_map::iterator unordered_map::erase(const_iterator position) { - return iterator(table_.erase(position.node_)); + return table_.erase(position); } template @@ -1156,7 +1156,7 @@ namespace unordered unordered_map::erase( const_iterator first, const_iterator last) { - return iterator(table_.erase_range(first.node_, last.node_)); + return table_.erase_range(first, last); } template @@ -1214,14 +1214,14 @@ namespace unordered typename unordered_map::iterator unordered_map::find(const key_type& k) { - return iterator(table_.find_node(k)); + return table_.find_node(k); } template typename unordered_map::const_iterator unordered_map::find(const key_type& k) const { - return const_iterator(table_.find_node(k)); + return table_.find_node(k); } template @@ -1233,7 +1233,7 @@ namespace unordered CompatibleHash const& hash, CompatiblePredicate const& eq) { - return iterator(table_.generic_find_node(k, hash, eq)); + return table_.generic_find_node(k, hash, eq); } template @@ -1245,7 +1245,7 @@ namespace unordered CompatibleHash const& hash, CompatiblePredicate const& eq) const { - return const_iterator(table_.generic_find_node(k, hash, eq)); + return table_.generic_find_node(k, hash, eq); } template @@ -1468,7 +1468,7 @@ namespace unordered typename unordered_multimap::iterator unordered_multimap::erase(const_iterator position) { - return iterator(table_.erase(position.node_)); + return table_.erase(position); } template @@ -1483,7 +1483,7 @@ namespace unordered unordered_multimap::erase( const_iterator first, const_iterator last) { - return iterator(table_.erase_range(first.node_, last.node_)); + return table_.erase_range(first, last); } template @@ -1520,14 +1520,14 @@ namespace unordered typename unordered_multimap::iterator unordered_multimap::find(const key_type& k) { - return iterator(table_.find_node(k)); + return table_.find_node(k); } template typename unordered_multimap::const_iterator unordered_multimap::find(const key_type& k) const { - return const_iterator(table_.find_node(k)); + return table_.find_node(k); } template @@ -1539,7 +1539,7 @@ namespace unordered CompatibleHash const& hash, CompatiblePredicate const& eq) { - return iterator(table_.generic_find_node(k, hash, eq)); + return table_.generic_find_node(k, hash, eq); } template @@ -1551,7 +1551,7 @@ namespace unordered CompatibleHash const& hash, CompatiblePredicate const& eq) const { - return const_iterator(table_.generic_find_node(k, hash, eq)); + return table_.generic_find_node(k, hash, eq); } template diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 1b2e5d82..1d56c777 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -201,12 +201,12 @@ namespace unordered iterator begin() { - return iterator(table_.begin()); + return table_.begin(); } const_iterator begin() const { - return const_iterator(table_.begin()); + return table_.begin(); } iterator end() @@ -221,7 +221,7 @@ namespace unordered const_iterator cbegin() const { - return const_iterator(table_.begin()); + return table_.begin(); } const_iterator cend() const @@ -1116,7 +1116,7 @@ namespace unordered typename unordered_set::iterator unordered_set::erase(const_iterator position) { - return iterator(table_.erase(position.node_)); + return table_.erase(position); } template @@ -1131,7 +1131,7 @@ namespace unordered unordered_set::erase( const_iterator first, const_iterator last) { - return iterator(table_.erase_range(first.node_, last.node_)); + return table_.erase_range(first, last); } template @@ -1168,7 +1168,7 @@ namespace unordered typename unordered_set::const_iterator unordered_set::find(const key_type& k) const { - return const_iterator(table_.find_node(k)); + return table_.find_node(k); } template @@ -1180,7 +1180,7 @@ namespace unordered CompatibleHash const& hash, CompatiblePredicate const& eq) const { - return const_iterator(table_.generic_find_node(k, hash, eq)); + return table_.generic_find_node(k, hash, eq); } template @@ -1394,7 +1394,7 @@ namespace unordered typename unordered_multiset::iterator unordered_multiset::erase(const_iterator position) { - return iterator(table_.erase(position.node_)); + return table_.erase(position); } template @@ -1409,7 +1409,7 @@ namespace unordered unordered_multiset::erase( const_iterator first, const_iterator last) { - return iterator(table_.erase_range(first.node_, last.node_)); + return table_.erase_range(first, last); } template @@ -1446,7 +1446,7 @@ namespace unordered typename unordered_multiset::const_iterator unordered_multiset::find(const key_type& k) const { - return const_iterator(table_.find_node(k)); + return table_.find_node(k); } template @@ -1458,7 +1458,7 @@ namespace unordered CompatibleHash const& hash, CompatiblePredicate const& eq) const { - return const_iterator(table_.generic_find_node(k, hash, eq)); + return table_.generic_find_node(k, hash, eq); } template