mirror of
https://github.com/boostorg/unordered.git
synced 2025-05-10 07:34:00 +00:00
Merged revisions 44076-44414 via svnmerge from https://svn.boost.org/svn/boost/branches/unordered/trunk ........ r44076 | danieljames | 2008-04-06 20:41:19 +0100 (Sun, 06 Apr 2008) | 1 line Move semantics for compilers with rvalue references. ........ r44077 | danieljames | 2008-04-06 20:48:59 +0100 (Sun, 06 Apr 2008) | 1 line Do move assignment 'properly'. ........ r44085 | danieljames | 2008-04-06 22:46:04 +0100 (Sun, 06 Apr 2008) | 1 line Use normal references for the move members, reset the source buckets_ pointer to stop the buckets getting deleted, and remove a superflous pointer check. ........ r44109 | danieljames | 2008-04-07 23:49:36 +0100 (Mon, 07 Apr 2008) | 1 line Add missing tests. ........ r44366 | danieljames | 2008-04-13 12:59:46 +0100 (Sun, 13 Apr 2008) | 1 line Avoid using rvalue references in the implementation files. ........ r44368 | danieljames | 2008-04-13 15:13:33 +0100 (Sun, 13 Apr 2008) | 6 lines Use a cut down version of the work in progress move library to implement move semantics on more compilers. Unfortunately the move constructor with allocator isn't really practical at the moment, since in the case where the container can't be moved, and the allocators aren't equal it will copy the container twice. ........ [SVN r44486]
725 lines
18 KiB
C++
725 lines
18 KiB
C++
|
|
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
|
// Copyright (C) 2005-2008 Daniel James.
|
|
// Distributed under 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)
|
|
|
|
// See http://www.boost.org/libs/unordered for documentation
|
|
|
|
#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>
|
|
|
|
#if !defined(BOOST_HAS_RVALUE_REFS)
|
|
#include <boost/unordered/detail/move.hpp>
|
|
#endif
|
|
|
|
namespace boost
|
|
{
|
|
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
|
|
{
|
|
typedef boost::unordered_detail::hash_types_unique_keys<
|
|
std::pair<const Key, T>, Key, Hash, Pred, Alloc
|
|
> implementation;
|
|
|
|
BOOST_DEDUCED_TYPENAME implementation::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 BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
|
|
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::local_iterator local_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::const_local_iterator const_local_iterator;
|
|
|
|
// construct/destroy/copy
|
|
|
|
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)
|
|
{
|
|
}
|
|
|
|
// TODO: Should this be explicit?
|
|
unordered_map(allocator_type const& a)
|
|
: base(boost::unordered_detail::default_initial_bucket_count,
|
|
hasher(), key_equal(), a)
|
|
{
|
|
}
|
|
|
|
unordered_map(unordered_map const& other, allocator_type const& a)
|
|
: base(other.base, a)
|
|
{
|
|
}
|
|
|
|
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)
|
|
{
|
|
}
|
|
|
|
#if defined(BOOST_HAS_RVALUE_REFS)
|
|
unordered_map(unordered_map&& other)
|
|
: base(other.base, boost::unordered_detail::move_tag())
|
|
{
|
|
}
|
|
|
|
unordered_map(unordered_map&& other, allocator_type const& a)
|
|
: base(other.base, a, boost::unordered_detail::move_tag())
|
|
{
|
|
}
|
|
|
|
unordered_map& operator=(unordered_map&& x)
|
|
{
|
|
base.move(x.base);
|
|
return *this;
|
|
}
|
|
#else
|
|
unordered_map(boost::unordered_detail::move_from<unordered_map> other)
|
|
: base(other.base, boost::unordered_detail::move_tag())
|
|
{
|
|
}
|
|
|
|
unordered_map& operator=(unordered_map x)
|
|
{
|
|
base.move(x.base);
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
private:
|
|
|
|
BOOST_DEDUCED_TYPENAME implementation::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.data_.begin());
|
|
}
|
|
|
|
const_iterator begin() const
|
|
{
|
|
return const_iterator(base.data_.begin());
|
|
}
|
|
|
|
iterator end()
|
|
{
|
|
return iterator(base.data_.end());
|
|
}
|
|
|
|
const_iterator end() const
|
|
{
|
|
return const_iterator(base.data_.end());
|
|
}
|
|
|
|
const_iterator cbegin() const
|
|
{
|
|
return const_iterator(base.data_.begin());
|
|
}
|
|
|
|
const_iterator cend() const
|
|
{
|
|
return const_iterator(base.data_.end());
|
|
}
|
|
|
|
// modifiers
|
|
|
|
std::pair<iterator, bool> insert(const value_type& obj)
|
|
{
|
|
return boost::unordered_detail::pair_cast<iterator, bool>(
|
|
base.insert(obj));
|
|
}
|
|
|
|
iterator insert(const_iterator hint, const value_type& obj)
|
|
{
|
|
return iterator(base.insert(get(hint), obj));
|
|
}
|
|
|
|
template <class InputIterator>
|
|
void insert(InputIterator first, InputIterator last)
|
|
{
|
|
base.insert(first, last);
|
|
}
|
|
|
|
iterator erase(const_iterator position)
|
|
{
|
|
return iterator(base.erase(get(position)));
|
|
}
|
|
|
|
size_type erase(const key_type& k)
|
|
{
|
|
return base.erase(k);
|
|
}
|
|
|
|
iterator erase(const_iterator first, const_iterator last)
|
|
{
|
|
return iterator(base.erase(get(first), get(last)));
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
base.data_.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;
|
|
}
|
|
|
|
mapped_type& at(const key_type& k)
|
|
{
|
|
return base.at(k).second;
|
|
}
|
|
|
|
mapped_type const& at(const key_type& k) const
|
|
{
|
|
return base.at(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.data_.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.data_.begin(n));
|
|
}
|
|
|
|
const_local_iterator begin(size_type n) const
|
|
{
|
|
return const_local_iterator(base.data_.begin(n));
|
|
}
|
|
|
|
local_iterator end(size_type n)
|
|
{
|
|
return local_iterator(base.data_.end(n));
|
|
}
|
|
|
|
const_local_iterator end(size_type n) const
|
|
{
|
|
return const_local_iterator(base.data_.end(n));
|
|
}
|
|
|
|
const_local_iterator cbegin(size_type n) const
|
|
{
|
|
return const_local_iterator(base.data_.begin(n));
|
|
}
|
|
|
|
const_local_iterator cend(size_type n) const
|
|
{
|
|
return const_local_iterator(base.data_.end(n));
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
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
|
|
{
|
|
typedef boost::unordered_detail::hash_types_equivalent_keys<
|
|
std::pair<const Key, T>, Key, Hash, Pred, Alloc
|
|
> implementation;
|
|
|
|
BOOST_DEDUCED_TYPENAME implementation::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 BOOST_DEDUCED_TYPENAME allocator_type::pointer pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_pointer const_pointer;
|
|
typedef BOOST_DEDUCED_TYPENAME allocator_type::reference reference;
|
|
typedef BOOST_DEDUCED_TYPENAME allocator_type::const_reference const_reference;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::size_type size_type;
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::difference_type difference_type;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::iterator iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::const_iterator const_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::local_iterator local_iterator;
|
|
typedef BOOST_DEDUCED_TYPENAME implementation::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)
|
|
{
|
|
}
|
|
|
|
unordered_multimap(allocator_type const& a)
|
|
: base(boost::unordered_detail::default_initial_bucket_count,
|
|
hasher(), key_equal(), a)
|
|
{
|
|
}
|
|
|
|
unordered_multimap(unordered_multimap const& other, allocator_type const& a)
|
|
: base(other.base, 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)
|
|
{
|
|
}
|
|
|
|
#if defined(BOOST_HAS_RVALUE_REFS)
|
|
unordered_multimap(unordered_multimap&& other)
|
|
: base(other.base, boost::unordered_detail::move_tag())
|
|
{
|
|
}
|
|
|
|
unordered_multimap(unordered_multimap&& other, allocator_type const& a)
|
|
: base(other.base, a, boost::unordered_detail::move_tag())
|
|
{
|
|
}
|
|
|
|
unordered_multimap& operator=(unordered_multimap&& x)
|
|
{
|
|
base.move(x.base);
|
|
return *this;
|
|
}
|
|
#else
|
|
unordered_multimap(boost::unordered_detail::move_from<unordered_multimap> other)
|
|
: base(other.base, boost::unordered_detail::move_tag())
|
|
{
|
|
}
|
|
|
|
unordered_multimap& operator=(unordered_multimap x)
|
|
{
|
|
base.move(x.base);
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
|
|
private:
|
|
|
|
BOOST_DEDUCED_TYPENAME implementation::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.data_.begin());
|
|
}
|
|
|
|
const_iterator begin() const
|
|
{
|
|
return const_iterator(base.data_.begin());
|
|
}
|
|
|
|
iterator end()
|
|
{
|
|
return iterator(base.data_.end());
|
|
}
|
|
|
|
const_iterator end() const
|
|
{
|
|
return const_iterator(base.data_.end());
|
|
}
|
|
|
|
const_iterator cbegin() const
|
|
{
|
|
return const_iterator(base.data_.begin());
|
|
}
|
|
|
|
const_iterator cend() const
|
|
{
|
|
return const_iterator(base.data_.end());
|
|
}
|
|
|
|
// modifiers
|
|
|
|
iterator insert(const value_type& obj)
|
|
{
|
|
return iterator(base.insert(obj));
|
|
}
|
|
|
|
iterator insert(const_iterator hint, const value_type& obj)
|
|
{
|
|
return iterator(base.insert(get(hint), obj));
|
|
}
|
|
|
|
template <class InputIterator>
|
|
void insert(InputIterator first, InputIterator last)
|
|
{
|
|
base.insert(first, last);
|
|
}
|
|
|
|
iterator erase(const_iterator position)
|
|
{
|
|
return iterator(base.erase(get(position)));
|
|
}
|
|
|
|
size_type erase(const key_type& k)
|
|
{
|
|
return base.erase(k);
|
|
}
|
|
|
|
iterator erase(const_iterator first, const_iterator last)
|
|
{
|
|
return iterator(base.erase(get(first), get(last)));
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
base.data_.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.data_.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.data_.begin(n));
|
|
}
|
|
|
|
const_local_iterator begin(size_type n) const
|
|
{
|
|
return const_local_iterator(base.data_.begin(n));
|
|
}
|
|
|
|
local_iterator end(size_type n)
|
|
{
|
|
return local_iterator(base.data_.end(n));
|
|
}
|
|
|
|
const_local_iterator end(size_type n) const
|
|
{
|
|
return const_local_iterator(base.data_.end(n));
|
|
}
|
|
|
|
const_local_iterator cbegin(size_type n) const
|
|
{
|
|
return const_local_iterator(base.data_.begin(n));
|
|
}
|
|
|
|
const_local_iterator cend(size_type n) const
|
|
{
|
|
return const_local_iterator(base.data_.end(n));
|
|
}
|
|
|
|
// 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
|