unordered/include/boost/unordered_map.hpp
Daniel James 9bd73e4ba7 New version of the unordered associative containers, with a more efficient data
structure for unordered_multimap/unordered_multiset that uses an extra
pointer per node but makes most operations more efficient when equivalent
nodes are present.

Now uses macros instead of template metaprogramming to implement the
differences between containers with equivalent and unique keys.

Removed the erase_iterator stuff which complicated matters more than it helped.
Now just using pointers with some helper functions.


[SVN r2950]
2006-05-07 13:24:17 +00:00

696 lines
18 KiB
C++

// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2006 Daniel James.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
// at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <functional>
#include <memory>
#include <boost/unordered/detail/hash_table.hpp>
#include <boost/functional/hash.hpp>
namespace boost
{
//! An unordered associative container that associates unique keys with another value.
/*! For full details see chapter 23 of the draft C++ standard.
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2009.pdf
*/
template <class Key,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class unordered_map
{
// Named for the benefit of Doxygen.
typedef boost::unordered_detail::hash_types_unique_keys<
std::pair<const Key, T>, Key, Hash, Pred, Alloc
> implementation_defined;
typename implementation_defined::hash_table base;
public:
// types
/*! Key must be Assignable and CopyConstructible.
*/
typedef Key key_type;
typedef std::pair<const Key, T> value_type;
typedef T mapped_type;
/*! Hash is a unary function object type such for hf of type hasher
* hf(x) has type std::size_t.
*/
typedef Hash hasher;
/*! Pred is a binary predicate that takes two arguments of type Key.
* Pred is an equivalence realtion
*/
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
/*! A local_iterator object may be used to iterate through a single
* bucket, but may not be used to iterate across buckets.
*/
typedef typename implementation_defined::local_iterator local_iterator;
/*! A const_local_iterator object may be used to iterate through a single
* bucket, but may not be used to iterate across buckets.
*/
typedef typename implementation_defined::const_local_iterator
const_local_iterator;
// construct/destroy/copy
/*! Constructs an empty container with at least n buckets, using hf as
* the hash function and eq as the key equality predicate. a is used
* as the allocator.
*/
explicit unordered_map(
size_type n = boost::unordered_detail::default_initial_bucket_count,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(n, hf, eql, a)
{
}
/*! Constructs an empty container with at least n buckets, using hf as
* the hash function and eq as the key equality predicate, and inserts
* elements from [i,j) into it. a is used as the allocator.
*/
template <class InputIterator>
unordered_map(InputIterator f, InputIterator l)
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), allocator_type())
{
}
template <class InputIterator>
unordered_map(InputIterator f, InputIterator l,
size_type n,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(f, l, n, hf, eql, a)
{
}
private:
typename implementation_defined::iterator_base const&
get(const_iterator const& it)
{
return boost::unordered_detail::iterator_access::get(it);
}
public:
allocator_type get_allocator() const
{
return base.get_allocator();
}
// size and capacity
bool empty() const
{
return base.empty();
}
size_type size() const
{
return base.size();
}
size_type max_size() const
{
return base.max_size();
}
// iterators
iterator begin()
{
return iterator(base.begin());
}
const_iterator begin() const
{
return const_iterator(base.begin());
}
iterator end()
{
return iterator(base.end());
}
const_iterator end() const
{
return const_iterator(base.end());
}
const_iterator cbegin() const
{
return const_iterator(base.begin());
}
const_iterator cend() const
{
return const_iterator(base.end());
}
// modifiers
std::pair<iterator, bool> insert(const value_type& obj)
{
return boost::unordered_detail::pair_cast<iterator, bool>(
base.insert(obj));
}
iterator insert(iterator hint, const value_type& obj)
{
return iterator(base.insert(get(hint), obj));
}
const_iterator insert(const_iterator hint, const value_type& obj)
{
return const_iterator(base.insert(get(hint), obj));
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
base.insert(first, last);
}
iterator erase(iterator position)
{
return iterator(base.erase(get(position)));
}
const_iterator erase(const_iterator position)
{
return const_iterator(base.erase(get(position)));
}
size_type erase(const key_type& k)
{
return base.erase(k);
}
iterator erase(iterator first, iterator last)
{
return iterator(base.erase(get(first), get(last)));
}
const_iterator erase(const_iterator first, const_iterator last)
{
return const_iterator(base.erase(get(first), get(last)));
}
void clear()
{
base.clear();
}
void swap(unordered_map& other)
{
base.swap(other.base);
}
// observers
hasher hash_function() const
{
return base.hash_function();
}
key_equal key_eq() const
{
return base.key_eq();
}
mapped_type& operator[](const key_type &k)
{
return base[k].second;
}
// lookup
iterator find(const key_type& k)
{
return iterator(base.find(k));
}
const_iterator find(const key_type& k) const
{
return const_iterator(base.find(k));
}
size_type count(const key_type& k) const
{
return base.count(k);
}
std::pair<iterator, iterator>
equal_range(const key_type& k)
{
return boost::unordered_detail::pair_cast<iterator, iterator>(
base.equal_range(k));
}
std::pair<const_iterator, const_iterator>
equal_range(const key_type& k) const
{
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
base.equal_range(k));
}
// bucket interface
size_type bucket_count() const
{
return base.bucket_count();
}
size_type max_bucket_count() const
{
return base.max_bucket_count();
}
size_type bucket_size(size_type n) const
{
return base.bucket_size(n);
}
size_type bucket(const key_type& k) const
{
return base.bucket(k);
}
local_iterator begin(size_type n)
{
return local_iterator(base.begin(n));
}
const_local_iterator begin(size_type n) const
{
return const_local_iterator(base.begin(n));
}
local_iterator end(size_type n)
{
return local_iterator(base.end(n));
}
const_local_iterator end(size_type n) const
{
return const_local_iterator(base.end(n));
}
#if defined(BOOST_UNORDERED_LOCAL_CBEGIN)
const_local_iterator cbegin(size_type n) const
{
return const_local_iterator(base.begin(n));
}
const_local_iterator cend(size_type n) const
{
return const_local_iterator(base.end(n));
}
#endif
// hash policy
float load_factor() const
{
return base.load_factor();
}
float max_load_factor() const
{
return base.max_load_factor();
}
void max_load_factor(float m)
{
base.max_load_factor(m);
}
void rehash(size_type n)
{
base.rehash(n);
}
}; // class template unordered_map
template <class K, class T, class H, class P, class A>
void swap(unordered_map<K, T, H, P, A> &m1,
unordered_map<K, T, H, P, A> &m2)
{
m1.swap(m2);
}
//! An unordered associative container that associates equivalent keys with another value.
/*! For full details see chapter 23 of the draft C++ standard.
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2009.pdf
*/
template <class Key,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class unordered_multimap
{
// Named for the benefit of Doxygen.
typedef boost::unordered_detail::hash_types_equivalent_keys<
std::pair<const Key, T>, Key, Hash, Pred, Alloc
> implementation_defined;
typename implementation_defined::hash_table base;
public:
// types
typedef Key key_type;
typedef std::pair<const Key, T> value_type;
typedef T mapped_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::local_iterator local_iterator;
typedef typename implementation_defined::const_local_iterator const_local_iterator;
// construct/destroy/copy
explicit unordered_multimap(
size_type n = boost::unordered_detail::default_initial_bucket_count,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(n, hf, eql, a)
{
}
template <class InputIterator>
unordered_multimap(InputIterator f, InputIterator l)
: base(f, l, boost::unordered_detail::default_initial_bucket_count,
hasher(), key_equal(), allocator_type())
{
}
template <class InputIterator>
unordered_multimap(InputIterator f, InputIterator l,
size_type n,
const hasher &hf = hasher(),
const key_equal &eql = key_equal(),
const allocator_type &a = allocator_type())
: base(f, l, n, hf, eql, a)
{
}
private:
typename implementation_defined::iterator_base const&
get(const_iterator const& it)
{
return boost::unordered_detail::iterator_access::get(it);
}
public:
allocator_type get_allocator() const
{
return base.get_allocator();
}
// size and capacity
bool empty() const
{
return base.empty();
}
size_type size() const
{
return base.size();
}
size_type max_size() const
{
return base.max_size();
}
// iterators
iterator begin()
{
return iterator(base.begin());
}
const_iterator begin() const
{
return const_iterator(base.begin());
}
iterator end()
{
return iterator(base.end());
}
const_iterator end() const
{
return const_iterator(base.end());
}
const_iterator cbegin() const
{
return const_iterator(base.begin());
}
const_iterator cend() const
{
return const_iterator(base.end());
}
// modifiers
iterator insert(const value_type& obj)
{
return iterator(base.insert(obj));
}
iterator insert(iterator hint, const value_type& obj)
{
return iterator(base.insert(get(hint), obj));
}
const_iterator insert(const_iterator hint, const value_type& obj)
{
return const_iterator(base.insert(get(hint), obj));
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
base.insert(first, last);
}
iterator erase(iterator position)
{
return iterator(base.erase(get(position)));
}
const_iterator erase(const_iterator position)
{
return const_iterator(base.erase(get(position)));
}
size_type erase(const key_type& k)
{
return base.erase(k);
}
iterator erase(iterator first, iterator last)
{
return iterator(base.erase(get(first), get(last)));
}
const_iterator erase(const_iterator first, const_iterator last)
{
return const_iterator(base.erase(get(first), get(last)));
}
void clear()
{
base.clear();
}
void swap(unordered_multimap& other)
{
base.swap(other.base);
}
// observers
hasher hash_function() const
{
return base.hash_function();
}
key_equal key_eq() const
{
return base.key_eq();
}
// lookup
iterator find(const key_type& k)
{
return iterator(base.find(k));
}
const_iterator find(const key_type& k) const
{
return const_iterator(base.find(k));
}
size_type count(const key_type& k) const
{
return base.count(k);
}
std::pair<iterator, iterator>
equal_range(const key_type& k)
{
return boost::unordered_detail::pair_cast<iterator, iterator>(
base.equal_range(k));
}
std::pair<const_iterator, const_iterator>
equal_range(const key_type& k) const
{
return boost::unordered_detail::pair_cast<const_iterator, const_iterator>(
base.equal_range(k));
}
// bucket interface
size_type bucket_count() const
{
return base.bucket_count();
}
size_type max_bucket_count() const
{
return base.max_bucket_count();
}
size_type bucket_size(size_type n) const
{
return base.bucket_size(n);
}
size_type bucket(const key_type& k) const
{
return base.bucket(k);
}
local_iterator begin(size_type n)
{
return local_iterator(base.begin(n));
}
const_local_iterator begin(size_type n) const
{
return const_local_iterator(base.begin(n));
}
local_iterator end(size_type n)
{
return local_iterator(base.end(n));
}
const_local_iterator end(size_type n) const
{
return const_local_iterator(base.end(n));
}
#if defined(BOOST_UNORDERED_LOCAL_CBEGIN)
const_local_iterator cbegin(size_type n) const
{
return const_local_iterator(base.begin(n));
}
const_local_iterator cend(size_type n) const
{
return const_local_iterator(base.end(n));
}
#endif
// hash policy
float load_factor() const
{
return base.load_factor();
}
float max_load_factor() const
{
return base.max_load_factor();
}
void max_load_factor(float m)
{
base.max_load_factor(m);
}
void rehash(size_type n)
{
base.rehash(n);
}
}; // class template unordered_multimap
template <class K, class T, class H, class P, class A>
void swap(unordered_multimap<K, T, H, P, A> &m1,
unordered_multimap<K, T, H, P, A> &m2)
{
m1.swap(m2);
}
} // namespace boost
#endif // BOOST_UNORDERED_MAP_HPP_INCLUDED