Compare commits

..

5 Commits

Author SHA1 Message Date
Beman Dawes f5a6688925 Release 1.37.0
[SVN r51178]
2009-02-10 13:14:42 +00:00
Troy D. Straszheim f7c664a359 merge of cmake build files from trunk per beman
[SVN r50756]
2009-01-24 18:57:20 +00:00
Daniel James 0921f8076d Remove a tab.
Merged revisions 50452 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r50452 | danieljames | 2009-01-03 23:26:00 +0000 (Sat, 03 Jan 2009) | 1 line
  
  Remove a tab.
........


[SVN r50506]
2009-01-07 21:50:23 +00:00
Daniel James b8e8ffa242 Merge latest hash and unordered developments, and add support for initialiser
lists to config.

Merged revisions 49338,49924-49927,49955,50029,50118 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r49338 | danieljames | 2008-10-15 10:44:41 +0100 (Wed, 15 Oct 2008) | 2 lines
  
  Revert [49229], it fixes the same problem as [48674].
........
  r49924 | danieljames | 2008-11-24 22:55:14 +0000 (Mon, 24 Nov 2008) | 1 line
  
  Extra tests for equality with different hash functions.
........
  r49925 | danieljames | 2008-11-24 22:55:47 +0000 (Mon, 24 Nov 2008) | 1 line
  
  Document operator==/operator!= as undefined if the equality predicates aren't equivalent.
........
  r49926 | danieljames | 2008-11-24 22:56:04 +0000 (Mon, 24 Nov 2008) | 1 line
  
  Use a larger prime number list.
........
  r49927 | danieljames | 2008-11-24 23:15:55 +0000 (Mon, 24 Nov 2008) | 1 line
  
  Use aligned storage for the value.
........
  r49955 | danieljames | 2008-11-27 11:42:13 +0000 (Thu, 27 Nov 2008) | 1 line
  
  Wild stab at getting destruction working on more compilers.
........
  r50029 | danieljames | 2008-11-29 21:47:55 +0000 (Sat, 29 Nov 2008) | 1 line
  
  Workaround another in-place destruction.
........
  r50118 | danieljames | 2008-12-04 21:30:19 +0000 (Thu, 04 Dec 2008) | 1 line
  
  Add support for initializer lists to config and the unordered containers.
........


[SVN r50451]
2009-01-03 23:18:33 +00:00
Daniel James 07e715fceb Merged revisions 49661-49662,49666,49669,49735,49756,49770,49811 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r49661 | danieljames | 2008-11-09 12:03:45 +0000 (Sun, 09 Nov 2008) | 1 line
  
  Move hash detail headers out of boost/functional/detail.
........
  r49662 | danieljames | 2008-11-09 12:11:50 +0000 (Sun, 09 Nov 2008) | 1 line
  
  Add a forwarding header for container_fwd.hpp
........
  r49666 | danieljames | 2008-11-09 19:12:05 +0000 (Sun, 09 Nov 2008) | 1 line
  
  Avoid comparing default initialised iterators in position_iterator.
........
  r49669 | danieljames | 2008-11-09 21:57:38 +0000 (Sun, 09 Nov 2008) | 2 lines
  
  Add link to the header to the synopsis in reference documentation.
  Refs #2214
........
  r49735 | danieljames | 2008-11-14 12:51:00 +0000 (Fri, 14 Nov 2008) | 1 line
  
  Explicitly specify the template parameters in the unordered container friend, in order to avoid some warnings.
........
  r49756 | danieljames | 2008-11-14 16:11:16 +0000 (Fri, 14 Nov 2008) | 1 line
  
  Use pragmas to suppress a Visual C++ warning.
........
  r49770 | danieljames | 2008-11-15 13:07:29 +0000 (Sat, 15 Nov 2008) | 1 line
  
  Use the new swap library.
........
  r49811 | danieljames | 2008-11-16 23:10:00 +0000 (Sun, 16 Nov 2008) | 1 line
  
  Fix a typo.
........


[SVN r49855]
2008-11-20 22:53:20 +00:00
13 changed files with 380 additions and 173 deletions
+23
View File
@@ -0,0 +1,23 @@
#----------------------------------------------------------------------------
# This file was automatically generated from the original CMakeLists.txt file
# Add a variable to hold the headers for the library
set (lib_headers
unordered_map.hpp
unordered_set.hpp
unordered
)
# Add a library target to the build system
boost_library_project(
unordered
# SRCDIRS
# TESTDIRS
HEADERS ${lib_headers}
# DOCDIRS
# DESCRIPTION
MODULARIZED
# AUTHORS
# MAINTAINERS
)
+20
View File
@@ -42,4 +42,24 @@ First official release.
* Move all the implementation inside `boost/unordered`, to assist
modularization and hopefully make it easier to track changes in subversion.
[h2 Boost 1.38.0]
* Use [@../../libs/utility/swap.html `boost::swap`].
* [@https://svn.boost.org/trac/boost/ticket/2237 Ticket 2237]:
Document that the equality and inequality operators are undefined for two
objects if their equality predicates aren't equivalent. Thanks to Daniel
Krügler.
* [@https://svn.boost.org/trac/boost/ticket/1710 Ticket 1710]:
Use a larger prime number list. Thanks to Thorsten Ottosen and Hervé
Brönnimann.
* Use
[@../../libs/type_traits/doc/html/boost_typetraits/category/alignment.html
aligned storage] to store the types. This changes the way the allocator is
used to construct nodes. It used to construct the node with two calls to
the allocator's `construct` method - once for the pointers and once for the
value. It now constructs the node with a single call to construct and
then constructs the value using in place construction.
* Add support for C++0x initializer lists where they're available (currently
only g++ 4.4 in C++0x mode).
[endsect]
+10
View File
@@ -41,6 +41,16 @@ This is a simplified version of the example at
[@../../libs/unordered/examples/case_insensitive.hpp /libs/unordered/examples/case_insensitive.hpp]
which supports other locales and string types.
[caution
Be careful when using the equality (`==`) operator with custom equality
predicates, especially if you're using a function pointer. If you compare two
containers with different equality predicates then the result is undefined.
For most stateless function objects this is impossible - since you can only
compare objects with the same equality predicate you know the equality
predicates must be equal. But if you're using function pointers or a stateful
equality predicate (e.g. boost::function) then you can get into trouble.
]
[h2 Custom Types]
Similarly, a custom hash function can be used for custom types:
+16
View File
@@ -678,6 +678,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>bool</type>
<notes>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
</function>
<function name="operator!=">
@@ -700,6 +702,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>bool</type>
<notes>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
</function>
</free-function-group>
@@ -1406,6 +1410,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>bool</type>
<notes>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
</function>
<function name="operator!=">
@@ -1428,6 +1434,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>bool</type>
<notes>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
</function>
</free-function-group>
@@ -2185,6 +2193,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>bool</type>
<notes>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
</function>
<function name="operator!=">
@@ -2209,6 +2219,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>bool</type>
<notes>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
</function>
</free-function-group>
@@ -2927,6 +2939,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>bool</type>
<notes>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
</function>
<function name="operator!=">
@@ -2951,6 +2965,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<type>bool</type>
<notes>
<para>This is a boost extension.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
</function>
</free-function-group>
+11 -14
View File
@@ -26,9 +26,12 @@
#include <boost/static_assert.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/utility/swap.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
@@ -58,17 +61,6 @@ namespace boost {
static const std::size_t default_initial_bucket_count = 50;
static const float minimum_max_load_factor = 1e-3f;
template <class T>
inline void hash_swap(T& x, T& y)
{
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
std::swap(x,y);
#else
using std::swap;
swap(x, y);
#endif
}
inline std::size_t double_to_size_t(double f)
{
return f >= static_cast<double>((std::numeric_limits<std::size_t>::max)()) ?
@@ -86,8 +78,9 @@ namespace boost {
template<typename T>
std::size_t const prime_list_template<T>::value[] = {
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
5ul, 11ul, 17ul, 29ul, 37ul, 53ul, 67ul, 79ul,
97ul, 131ul, 193ul, 257ul, 389ul, 521ul, 769ul,
1031ul, 1543ul, 2053ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
@@ -230,7 +223,11 @@ namespace boost {
functions func2_;
functions_ptr func_; // The currently active functions.
};
template <typename T>
void destroy(T* x) {
x->~T();
}
}
}
@@ -34,7 +34,6 @@ namespace boost {
public:
typedef BOOST_UNORDERED_TABLE_DATA data;
struct node_base;
struct node;
struct bucket;
typedef std::size_t size_type;
@@ -45,9 +44,6 @@ namespace boost {
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, node>::type
node_allocator;
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, node_base>::type
node_base_allocator;
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, bucket>::type
bucket_allocator;
@@ -88,39 +84,36 @@ namespace boost {
}
};
// Value Base
struct value_base {
typename boost::aligned_storage<
sizeof(value_type),
boost::alignment_of<value_type>::value>::type data_;
void* address() { return this; }
};
// Hash Node
//
// all no throw
struct node_base : bucket
{
struct node : value_base, bucket {
#if BOOST_UNORDERED_EQUIVALENT_KEYS
public:
node_base() : group_prev_()
node() : group_prev_()
{
BOOST_UNORDERED_MSVC_RESET_PTR(group_prev_);
}
link_ptr group_prev_;
#endif
value_type& value() {
return *static_cast<value_type*>(this->address());
}
};
struct node : node_base
{
public:
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <typename... Args>
node(Args&&... args)
: node_base(), value_(std::forward<Args>(args)...) {}
#else
node(value_type const& v) : node_base(), value_(v) {}
#endif
value_type value_;
};
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
// allocators
//
// Stores all the allocators that we're going to need.
@@ -136,15 +129,17 @@ namespace boost {
void destroy(link_ptr ptr)
{
node_ptr n(node_alloc_.address(*static_cast<node*>(&*ptr)));
node* raw_ptr = static_cast<node*>(&*ptr);
boost::unordered_detail::destroy(&raw_ptr->value());
node_ptr n(node_alloc_.address(*raw_ptr));
node_alloc_.destroy(n);
node_alloc_.deallocate(n, 1);
}
void swap(allocators& x)
{
unordered_detail::hash_swap(node_alloc_, x.node_alloc_);
unordered_detail::hash_swap(bucket_alloc_, x.bucket_alloc_);
boost::swap(node_alloc_, x.node_alloc_);
boost::swap(bucket_alloc_, x.bucket_alloc_);
}
bool operator==(allocators const& x)
@@ -163,146 +158,62 @@ namespace boost {
node_ptr node_;
bool node_constructed_;
bool value_constructed_;
public:
node_constructor(allocators& a)
: allocators_(a),
node_(), node_constructed_(false)
node_(), node_constructed_(false), value_constructed_(false)
{
}
~node_constructor()
{
if (node_) {
if (value_constructed_) {
boost::unordered_detail::destroy(&node_->value());
}
if (node_constructed_)
allocators_.node_alloc_.destroy(node_);
allocators_.node_alloc_.deallocate(node_, 1);
}
}
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <typename... Args>
void construct(Args&&... args)
{
BOOST_ASSERT(!node_);
node_constructed_ = false;
value_constructed_ = false;
node_ = allocators_.node_alloc_.allocate(1);
allocators_.node_alloc_.construct(node_, std::forward<Args>(args)...);
allocators_.node_alloc_.construct(node_, node());
node_constructed_ = true;
}
node_ptr get() const
{
BOOST_ASSERT(node_);
return node_;
new(node_->address()) value_type(std::forward<Args>(args)...);
value_constructed_ = true;
}
// no throw
link_ptr release()
{
node_ptr p = node_;
unordered_detail::reset(node_);
return link_ptr(allocators_.bucket_alloc_.address(*p));
}
private:
node_constructor(node_constructor const&);
node_constructor& operator=(node_constructor const&);
};
#else
// allocators
//
// Stores all the allocators that we're going to need.
struct allocators
{
node_allocator node_alloc_;
bucket_allocator bucket_alloc_;
value_allocator value_alloc_;
node_base_allocator node_base_alloc_;
allocators(value_allocator const& a)
: node_alloc_(a), bucket_alloc_(a),
value_alloc_(a), node_base_alloc_(a)
{}
void destroy(link_ptr ptr)
{
node_ptr n(node_alloc_.address(*static_cast<node*>(&*ptr)));
value_alloc_.destroy(value_alloc_.address(n->value_));
node_base_alloc_.destroy(node_base_alloc_.address(*n));
node_alloc_.deallocate(n, 1);
}
void swap(allocators& x)
{
unordered_detail::hash_swap(node_alloc_, x.node_alloc_);
unordered_detail::hash_swap(bucket_alloc_, x.bucket_alloc_);
unordered_detail::hash_swap(value_alloc_, x.value_alloc_);
unordered_detail::hash_swap(node_base_alloc_, x.node_base_alloc_);
}
bool operator==(allocators const& x)
{
return value_alloc_ == x.value_alloc_;
}
};
// node_constructor
//
// Used to construct nodes in an exception safe manner.
class node_constructor
{
allocators& allocators_;
node_ptr node_;
bool value_constructed_;
bool node_base_constructed_;
public:
node_constructor(allocators& a)
: allocators_(a),
node_(), value_constructed_(false), node_base_constructed_(false)
{
BOOST_UNORDERED_MSVC_RESET_PTR(node_);
}
~node_constructor()
{
if (node_) {
if (value_constructed_)
allocators_.value_alloc_.destroy(
allocators_.value_alloc_.address(node_->value_));
if (node_base_constructed_)
allocators_.node_base_alloc_.destroy(
allocators_.node_base_alloc_.address(*node_));
allocators_.node_alloc_.deallocate(node_, 1);
}
}
template <typename V>
void construct(V const& v)
{
BOOST_ASSERT(!node_);
node_constructed_ = false;
value_constructed_ = false;
node_base_constructed_ = false;
node_ = allocators_.node_alloc_.allocate(1);
allocators_.node_base_alloc_.construct(
allocators_.node_base_alloc_.address(*node_),
node_base());
node_base_constructed_ = true;
allocators_.node_alloc_.construct(node_, node());
node_constructed_ = true;
allocators_.value_alloc_.construct(
allocators_.value_alloc_.address(node_->value_), v);
new(node_->address()) value_type(v);
value_constructed_ = true;
}
#endif
node_ptr get() const
{
@@ -322,7 +233,6 @@ namespace boost {
node_constructor(node_constructor const&);
node_constructor& operator=(node_constructor const&);
};
#endif
// Methods for navigating groups of elements with equal keys.
@@ -351,8 +261,7 @@ namespace boost {
// pre: Must be pointing to a node
static inline reference get_value(link_ptr p) {
BOOST_ASSERT(p);
return static_cast<node*>(&*p)->value_;
return get_node(p).value();
}
class iterator_base
@@ -1357,17 +1266,10 @@ namespace boost {
// accessors
// no throw
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
node_allocator get_allocator() const
{
return data_.allocators_.node_alloc_;
}
#else
value_allocator get_allocator() const
{
return data_.allocators_.value_alloc_;
}
#endif
// no throw
hasher const& hash_function() const
@@ -1469,6 +1371,21 @@ namespace boost {
return need_to_reserve;
}
// basic exception safety
bool reserve_for_insert(size_type n)
{
bool need_to_reserve = n >= max_load_;
// throws - basic:
if (need_to_reserve) {
size_type s = size();
s = s + (s >> 1);
s = s > n ? s : n;
rehash_impl(min_buckets_for_size(s));
}
BOOST_ASSERT(n < max_load_ || n > max_size());
return need_to_reserve;
}
public:
// no throw
@@ -1713,14 +1630,14 @@ namespace boost {
iterator_base insert_impl(node_constructor& a)
{
key_type const& k = extract_key(a.get()->value_);
key_type const& k = extract_key(a.get()->value());
size_type hash_value = hash_function()(k);
bucket_ptr bucket = data_.bucket_ptr_from_hash(hash_value);
link_ptr position = find_iterator(bucket, k);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(reserve(size() + 1))
if(reserve_for_insert(size() + 1))
bucket = data_.bucket_ptr_from_hash(hash_value);
// I'm relying on link_ptr not being invalidated by
@@ -1735,7 +1652,7 @@ namespace boost {
iterator_base insert_hint_impl(iterator_base const& it, node_constructor& a)
{
// equal can throw, but with no effects
if (it == data_.end() || !equal(extract_key(a.get()->value_), *it)) {
if (it == data_.end() || !equal(extract_key(a.get()->value()), *it)) {
// Use the standard insert if the iterator doesn't point
// to a matching key.
return insert_impl(a);
@@ -1750,8 +1667,8 @@ namespace boost {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
bucket_ptr base = reserve(size() + 1) ?
get_bucket(extract_key(a.get()->value_)) : it.bucket_;
bucket_ptr base = reserve_for_insert(size() + 1) ?
get_bucket(extract_key(a.get()->value())) : it.bucket_;
// Nothing after this point can throw
@@ -1775,13 +1692,13 @@ namespace boost {
}
else {
// Only require basic exception safety here
reserve(size() + distance);
reserve_for_insert(size() + distance);
node_constructor a(data_.allocators_);
for (; i != j; ++i) {
a.construct(*i);
key_type const& k = extract_key(a.get()->value_);
key_type const& k = extract_key(a.get()->value());
bucket_ptr bucket = get_bucket(k);
link_ptr position = find_iterator(bucket, k);
@@ -1841,7 +1758,7 @@ namespace boost {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(reserve(size() + 1))
if(reserve_for_insert(size() + 1))
bucket = data_.bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
@@ -1880,7 +1797,7 @@ namespace boost {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(reserve(size() + 1))
if(reserve_for_insert(size() + 1))
bucket = data_.bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
@@ -1947,7 +1864,7 @@ namespace boost {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(reserve(size() + 1))
if(reserve_for_insert(size() + 1))
bucket = data_.bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
@@ -1966,7 +1883,7 @@ namespace boost {
a.construct(std::forward<Args>(args)...);
// No side effects in this initial code
key_type const& k = extract_key(a.get()->value_);
key_type const& k = extract_key(a.get()->value());
size_type hash_value = hash_function()(k);
bucket_ptr bucket = data_.bucket_ptr_from_hash(hash_value);
link_ptr pos = find_iterator(bucket, k);
@@ -1978,7 +1895,7 @@ namespace boost {
} else {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(reserve(size() + 1))
if(reserve_for_insert(size() + 1))
bucket = data_.bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
@@ -2047,7 +1964,7 @@ namespace boost {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(size() + 1 >= max_load_) {
reserve(size() + insert_size(i, j));
reserve_for_insert(size() + insert_size(i, j));
bucket = data_.bucket_ptr_from_hash(hash_value);
}
+53 -4
View File
@@ -21,6 +21,15 @@
#include <boost/unordered/detail/move.hpp>
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
#if BOOST_MSVC >= 1400
#pragma warning(disable:4396) //the inline specifier cannot be used when a
// friend declaration refers to a specialization
// of a function template
#endif
#endif
namespace boost
{
template <class Key, class T, class Hash, class Pred, class Alloc>
@@ -126,6 +135,24 @@ namespace boost
#endif
#endif
#if !defined(BOOST_NO_INITIALIZER_LISTS)
unordered_map(std::initializer_list<value_type> list,
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(list.begin(), list.end(), n, hf, eql, a)
{
}
unordered_map& operator=(std::initializer_list<value_type> list)
{
base.data_.clear();
base.insert_range(list.begin(), list.end());
return *this;
}
#endif
private:
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
@@ -385,8 +412,8 @@ namespace boost
friend bool operator==(unordered_map const&, unordered_map const&);
friend bool operator!=(unordered_map const&, unordered_map const&);
#else
friend bool operator==<>(unordered_map const&, unordered_map const&);
friend bool operator!=<>(unordered_map const&, unordered_map const&);
friend bool operator==<Key, T, Hash, Pred, Alloc>(unordered_map const&, unordered_map const&);
friend bool operator!=<Key, T, Hash, Pred, Alloc>(unordered_map const&, unordered_map const&);
#endif
}; // class template unordered_map
@@ -514,6 +541,24 @@ namespace boost
#endif
#endif
#if !defined(BOOST_NO_INITIALIZER_LISTS)
unordered_multimap(std::initializer_list<value_type> list,
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(list.begin(), list.end(), n, hf, eql, a)
{
}
unordered_multimap& operator=(std::initializer_list<value_type> list)
{
base.data_.clear();
base.insert_range(list.begin(), list.end());
return *this;
}
#endif
private:
@@ -757,8 +802,8 @@ namespace boost
friend bool operator==(unordered_multimap const&, unordered_multimap const&);
friend bool operator!=(unordered_multimap const&, unordered_multimap const&);
#else
friend bool operator==<>(unordered_multimap const&, unordered_multimap const&);
friend bool operator!=<>(unordered_multimap const&, unordered_multimap const&);
friend bool operator==<Key, T, Hash, Pred, Alloc>(unordered_multimap const&, unordered_multimap const&);
friend bool operator!=<Key, T, Hash, Pred, Alloc>(unordered_multimap const&, unordered_multimap const&);
#endif
}; // class template unordered_multimap
@@ -785,4 +830,8 @@ namespace boost
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif // BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
+53 -4
View File
@@ -21,6 +21,15 @@
#include <boost/unordered/detail/move.hpp>
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
#if BOOST_MSVC >= 1400
#pragma warning(disable:4396) //the inline specifier cannot be used when a
// friend declaration refers to a specialization
// of a function template
#endif
#endif
namespace boost
{
template <class Value, class Hash, class Pred, class Alloc>
@@ -124,6 +133,24 @@ namespace boost
#endif
#endif
#if !defined(BOOST_NO_INITIALIZER_LISTS)
unordered_set(std::initializer_list<value_type> list,
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(list.begin(), list.end(), n, hf, eql, a)
{
}
unordered_set& operator=(std::initializer_list<value_type> list)
{
base.data_.clear();
base.insert_range(list.begin(), list.end());
return *this;
}
#endif
private:
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
@@ -357,8 +384,8 @@ namespace boost
friend bool operator==(unordered_set const&, unordered_set const&);
friend bool operator!=(unordered_set const&, unordered_set const&);
#else
friend bool operator==<>(unordered_set const&, unordered_set const&);
friend bool operator!=<>(unordered_set const&, unordered_set const&);
friend bool operator==<Value, Hash, Pred, Alloc>(unordered_set const&, unordered_set const&);
friend bool operator!=<Value, Hash, Pred, Alloc>(unordered_set const&, unordered_set const&);
#endif
}; // class template unordered_set
@@ -484,6 +511,24 @@ namespace boost
#endif
#endif
#if !defined(BOOST_NO_INITIALIZER_LISTS)
unordered_multiset(std::initializer_list<value_type> list,
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(list.begin(), list.end(), n, hf, eql, a)
{
}
unordered_multiset& operator=(std::initializer_list<value_type> list)
{
base.data_.clear();
base.insert_range(list.begin(), list.end());
return *this;
}
#endif
private:
BOOST_DEDUCED_TYPENAME implementation::iterator_base const&
@@ -714,8 +759,8 @@ namespace boost
friend bool operator==(unordered_multiset const&, unordered_multiset const&);
friend bool operator!=(unordered_multiset const&, unordered_multiset const&);
#else
friend bool operator==<>(unordered_multiset const&, unordered_multiset const&);
friend bool operator!=<>(unordered_multiset const&, unordered_multiset const&);
friend bool operator==<Value, Hash, Pred, Alloc>(unordered_multiset const&, unordered_multiset const&);
friend bool operator!=<Value, Hash, Pred, Alloc>(unordered_multiset const&, unordered_multiset const&);
#endif
}; // class template unordered_multiset
@@ -742,4 +787,8 @@ namespace boost
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif // BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
+1
View File
@@ -0,0 +1 @@
boost_module(unordered DEPENDS config functional)
+75
View File
@@ -0,0 +1,75 @@
boost_additional_test_dependencies(unordered BOOST_DEPENDS test)
# GCC Compilers
IF(CMAKE_COMPILER_IS_GNUCC)
SET(test_compile_flags "-Wsign-promo -Wunused-parameter")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
# Intel Compiler flags
IF( ${CMAKE_CXX_COMPILER} MATCHES "icpc" )
SET(test_compile_flags "${test_compile_flags} -strict_ansi -cxxlib-icc")
ENDIF( ${CMAKE_CXX_COMPILER} MATCHES "icpc" )
set (swap_compile_flags "${test_compile_flags} -DBOOST_UNORDERED_SWAP_METHOD=2")
#-------------------------------------------------------------------------------
# Unordered Tests
set (unordered_tests
fwd_set_test
fwd_map_test
compile_set
compile_map
link_test_1
link_test_2
simple_tests
equivalent_keys_tests
constructor_tests
copy_tests
move_tests.cpp
assign_tests
insert_tests
insert_stable_tests
unnecessary_copy_tests
erase_tests
erase_equiv_tests
find_tests
at_tests
bucket_tests
load_factor_tests
rehash_tests
equality_tests
)
#-- Create an executable test for each source
foreach(test ${unordered_tests})
boost_test_run(${test} "unordered/${test}.cpp"
COMPILE_FLAGS ${test_compile_flags}
DEPENDS boost_unit_test_framework)
endforeach(test ${unordered_tests})
#-- run the swap test
boost_test_run(swap_tests
COMPILE_FLAGS ${swap_compile_flags}
DEPENDS boost_unit_test_framework)
#-------------------------------------------------------------------------------
# Exception Tests
set (exception_tests
constructor_exception_tests
copy_exception_tests
assign_exception_tests
insert_exception_tests
erase_exception_tests
rehash_exception_tests
)
#-- Create an executable test for each source
foreach(test ${exception_tests})
boost_test_run(${test} "exception/${test}.cpp"
COMPILE_FLAGS ${test_compile_flags}
DEPENDS boost_unit_test_framework)
endforeach(test ${unordered_tests})
#-- run the swap test
boost_test_run(swap_swap_exception_tests
COMPILE_FLAGS ${swap_compile_flags}
DEPENDS boost_unit_test_framework)
+16
View File
@@ -103,6 +103,22 @@ UNORDERED_TEST(assign_tests2,
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
std::cerr<<"Initializer List Tests\n";
boost::unordered_set<int> x;
x.insert(10);
x.insert(20);
x = { 1, 2, -10 };
BOOST_CHECK(x.find(10) == x.end());
BOOST_CHECK(x.find(-10) != x.end());
}
#endif
}
RUN_TESTS()
+11
View File
@@ -288,6 +288,17 @@ UNORDERED_TEST(map_constructor_test,
((test_map)(test_multimap))
)
#if !defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(test_initializer_list) {
std::cerr<<"Initializer List Tests\n";
boost::unordered_set<int> x1 = { 2, 10, 45, -5 };
BOOST_CHECK(x1.find(10) != x1.end());
BOOST_CHECK(x1.find(46) == x1.end());
}
#endif
}
RUN_TESTS()
+24 -1
View File
@@ -13,6 +13,10 @@ namespace equality_tests
{
struct mod_compare
{
bool alt_hash_;
explicit mod_compare(bool alt_hash = false) : alt_hash_(alt_hash) {}
bool operator()(int x, int y) const
{
return x % 1000 == y % 1000;
@@ -20,7 +24,7 @@ namespace equality_tests
int operator()(int x) const
{
return x % 250;
return alt_hash_ ? x % 250 : (x + 5) % 250;
}
};
@@ -138,6 +142,25 @@ namespace equality_tests
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)));
}
// Test that equality still works when the two containers have
// different hash functions but the same equality predicate.
UNORDERED_AUTO_TEST(equality_different_hash_test)
{
typedef boost::unordered_set<int, mod_compare, mod_compare> set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
BOOST_CHECK(set1 == set2);
set1.insert(1); set2.insert(2);
BOOST_CHECK(set1 != set2);
set1.insert(2); set2.insert(1);
BOOST_CHECK(set1 == set2);
set1.insert(10); set2.insert(20);
BOOST_CHECK(set1 != set2);
set1.insert(20); set2.insert(10);
BOOST_CHECK(set1 == set2);
}
}
RUN_TESTS()