Merge unordered and hash.

Improved Codegear support in unordered.
Another warning suppression in hash.


[SVN r58223]
This commit is contained in:
Daniel James
2009-12-07 19:26:26 +00:00
parent 144d8963a3
commit 02bf8f288e
13 changed files with 265 additions and 86 deletions

View File

@ -102,5 +102,10 @@ First official release.
* Buckets are allocated lazily which means that constructing an empty container
will not allocate any memory.
[h2 Boost 1.42.0]
* Support instantiating the containers with incomplete value types.
* Reduced the number of warnings (mostly in tests).
[endsect]

View File

@ -288,6 +288,9 @@ namespace boost { namespace unordered_detail {
{
if (node_) {
if (value_constructed_) {
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { hash_node<Alloc, Grouped> x; };
#endif
boost::unordered_detail::destroy(&node_->value());
}

View File

@ -38,16 +38,16 @@
namespace boost
{
template <class Key, class T, class Hash, class Pred, class Alloc>
template <class K, class T, class H, class P, class A>
class unordered_map
{
public:
typedef Key key_type;
typedef std::pair<const Key, T> value_type;
typedef K key_type;
typedef std::pair<const K, T> value_type;
typedef T mapped_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef H hasher;
typedef P key_equal;
typedef A allocator_type;
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
private:
@ -58,7 +58,7 @@ namespace boost
allocator_type, value_type>::type
value_allocator;
typedef boost::unordered_detail::map<Key, Hash, Pred,
typedef boost::unordered_detail::map<K, H, P,
value_allocator> types;
typedef BOOST_DEDUCED_TYPENAME types::impl table;
@ -177,7 +177,7 @@ namespace boost
}
#else
unordered_map(boost::unordered_detail::move_from<
unordered_map<Key, T, Hash, Pred, Alloc>
unordered_map<K, T, H, P, A>
> other)
: table_(other.source.table_, boost::unordered_detail::move_tag())
{
@ -284,6 +284,7 @@ namespace boost
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
std::pair<iterator, bool> emplace(value_type const& v = value_type())
{
return boost::unordered_detail::pair_cast<iterator, bool>(
@ -294,6 +295,7 @@ namespace boost
{
return iterator(table_.emplace(v).first);
}
#endif
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template < \
@ -511,9 +513,9 @@ namespace boost
}
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<Key, T, Hash, Pred, Alloc>(
friend bool operator==<K, T, H, P, A>(
unordered_map const&, unordered_map const&);
friend bool operator!=<Key, T, Hash, Pred, Alloc>(
friend bool operator!=<K, T, H, P, A>(
unordered_map const&, unordered_map const&);
#endif
}; // class template unordered_map
@ -522,6 +524,9 @@ namespace boost
inline bool operator==(unordered_map<K, T, H, P, A> const& m1,
unordered_map<K, T, H, P, A> const& m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_map<K,T,H,P,A> x; };
#endif
return m1.table_.equals(m2.table_);
}
@ -529,6 +534,9 @@ namespace boost
inline bool operator!=(unordered_map<K, T, H, P, A> const& m1,
unordered_map<K, T, H, P, A> const& m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_map<K,T,H,P,A> x; };
#endif
return !m1.table_.equals(m2.table_);
}
@ -536,20 +544,23 @@ namespace boost
inline void swap(unordered_map<K, T, H, P, A> &m1,
unordered_map<K, T, H, P, A> &m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_map<K,T,H,P,A> x; };
#endif
m1.swap(m2);
}
template <class Key, class T, class Hash, class Pred, class Alloc>
template <class K, class T, class H, class P, class A>
class unordered_multimap
{
public:
typedef Key key_type;
typedef std::pair<const Key, T> value_type;
typedef K key_type;
typedef std::pair<const K, T> value_type;
typedef T mapped_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef H hasher;
typedef P key_equal;
typedef A allocator_type;
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
private:
@ -560,7 +571,7 @@ namespace boost
allocator_type, value_type>::type
value_allocator;
typedef boost::unordered_detail::multimap<Key, Hash, Pred,
typedef boost::unordered_detail::multimap<K, H, P,
value_allocator> types;
typedef BOOST_DEDUCED_TYPENAME types::impl table;
@ -680,7 +691,7 @@ namespace boost
}
#else
unordered_multimap(boost::unordered_detail::move_from<
unordered_multimap<Key, T, Hash, Pred, Alloc>
unordered_multimap<K, T, H, P, A>
> other)
: table_(other.source.table_, boost::unordered_detail::move_tag())
{
@ -786,6 +797,7 @@ namespace boost
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
iterator emplace(value_type const& v = value_type())
{
return iterator(table_.emplace(v));
@ -796,7 +808,7 @@ namespace boost
{
return iterator(table_.emplace(v));
}
#endif
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template < \
@ -999,9 +1011,9 @@ namespace boost
}
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<Key, T, Hash, Pred, Alloc>(
friend bool operator==<K, T, H, P, A>(
unordered_multimap const&, unordered_multimap const&);
friend bool operator!=<Key, T, Hash, Pred, Alloc>(
friend bool operator!=<K, T, H, P, A>(
unordered_multimap const&, unordered_multimap const&);
#endif
}; // class template unordered_multimap
@ -1010,6 +1022,9 @@ namespace boost
inline bool operator==(unordered_multimap<K, T, H, P, A> const& m1,
unordered_multimap<K, T, H, P, A> const& m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_multimap<K,T,H,P,A> x; };
#endif
return m1.table_.equals(m2.table_);
}
@ -1017,6 +1032,9 @@ namespace boost
inline bool operator!=(unordered_multimap<K, T, H, P, A> const& m1,
unordered_multimap<K, T, H, P, A> const& m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_multimap<K,T,H,P,A> x; };
#endif
return !m1.table_.equals(m2.table_);
}
@ -1024,6 +1042,9 @@ namespace boost
inline void swap(unordered_multimap<K, T, H, P, A> &m1,
unordered_multimap<K, T, H, P, A> &m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_multimap<K,T,H,P,A> x; };
#endif
m1.swap(m2);
}

View File

@ -17,11 +17,11 @@
namespace boost
{
template <class Key,
template <class K,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class H = hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
template <class K, class T, class H, class P, class A>
bool operator==(unordered_map<K, T, H, P, A> const&,
@ -33,11 +33,11 @@ namespace boost
void swap(unordered_map<K, T, H, P, A>&,
unordered_map<K, T, H, P, A>&);
template <class Key,
template <class K,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class H = hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class K, class T, class H, class P, class A>
bool operator==(unordered_multimap<K, T, H, P, A> const&,

View File

@ -38,16 +38,16 @@
namespace boost
{
template <class Value, class Hash, class Pred, class Alloc>
template <class T, class H, class P, class A>
class unordered_set
{
public:
typedef Value key_type;
typedef Value value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef T key_type;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef A allocator_type;
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
private:
@ -58,7 +58,7 @@ namespace boost
allocator_type, value_type>::type
value_allocator;
typedef boost::unordered_detail::set<Hash, Pred,
typedef boost::unordered_detail::set<H, P,
value_allocator> types;
typedef BOOST_DEDUCED_TYPENAME types::impl table;
@ -171,7 +171,7 @@ namespace boost
}
#else
unordered_set(boost::unordered_detail::move_from<
unordered_set<Value, Hash, Pred, Alloc>
unordered_set<T, H, P, A>
> other)
: table_(other.source.table_, boost::unordered_detail::move_tag())
{
@ -478,9 +478,9 @@ namespace boost
}
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<Value, Hash, Pred, Alloc>(
friend bool operator==<T, H, P, A>(
unordered_set const&, unordered_set const&);
friend bool operator!=<Value, Hash, Pred, Alloc>(
friend bool operator!=<T, H, P, A>(
unordered_set const&, unordered_set const&);
#endif
}; // class template unordered_set
@ -489,6 +489,9 @@ namespace boost
inline bool operator==(unordered_set<T, H, P, A> const& m1,
unordered_set<T, H, P, A> const& m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_set<T,H,P,A> x; };
#endif
return m1.table_.equals(m2.table_);
}
@ -496,6 +499,9 @@ namespace boost
inline bool operator!=(unordered_set<T, H, P, A> const& m1,
unordered_set<T, H, P, A> const& m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_set<T,H,P,A> x; };
#endif
return !m1.table_.equals(m2.table_);
}
@ -503,19 +509,22 @@ namespace boost
inline void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_set<T,H,P,A> x; };
#endif
m1.swap(m2);
}
template <class Value, class Hash, class Pred, class Alloc>
template <class T, class H, class P, class A>
class unordered_multiset
{
public:
typedef Value key_type;
typedef Value value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Alloc allocator_type;
typedef T key_type;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef A allocator_type;
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
private:
@ -526,7 +535,7 @@ namespace boost
allocator_type, value_type>::type
value_allocator;
typedef boost::unordered_detail::multiset<Hash, Pred,
typedef boost::unordered_detail::multiset<H, P,
value_allocator> types;
typedef BOOST_DEDUCED_TYPENAME types::impl table;
@ -640,7 +649,7 @@ namespace boost
}
#else
unordered_multiset(boost::unordered_detail::move_from<
unordered_multiset<Value, Hash, Pred, Alloc>
unordered_multiset<T, H, P, A>
> other)
: table_(other.source.table_, boost::unordered_detail::move_tag())
{
@ -943,9 +952,9 @@ namespace boost
}
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<Value, Hash, Pred, Alloc>(
friend bool operator==<T, H, P, A>(
unordered_multiset const&, unordered_multiset const&);
friend bool operator!=<Value, Hash, Pred, Alloc>(
friend bool operator!=<T, H, P, A>(
unordered_multiset const&, unordered_multiset const&);
#endif
}; // class template unordered_multiset
@ -954,6 +963,9 @@ namespace boost
inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
unordered_multiset<T, H, P, A> const& m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_multiset<T,H,P,A> x; };
#endif
return m1.table_.equals(m2.table_);
}
@ -961,6 +973,9 @@ namespace boost
inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
unordered_multiset<T, H, P, A> const& m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_multiset<T,H,P,A> x; };
#endif
return !m1.table_.equals(m2.table_);
}
@ -968,6 +983,9 @@ namespace boost
inline void swap(unordered_multiset<T, H, P, A> &m1,
unordered_multiset<T, H, P, A> &m2)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { unordered_multiset<T,H,P,A> x; };
#endif
m1.swap(m2);
}

View File

@ -17,10 +17,10 @@
namespace boost
{
template <class Value,
class Hash = hash<Value>,
class Pred = std::equal_to<Value>,
class Alloc = std::allocator<Value> >
template <class T,
class H = hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
template <class T, class H, class P, class A>
bool operator==(unordered_set<T, H, P, A> const&,
@ -32,10 +32,10 @@ namespace boost
void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2);
template <class Value,
class Hash = hash<Value>,
class Pred = std::equal_to<Value>,
class Alloc = std::allocator<Value> >
template <class T,
class H = hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
template <class T, class H, class P, class A>
bool operator==(unordered_multiset<T, H, P, A> const&,

View File

@ -126,8 +126,9 @@ struct input_range_construct_test : public range<T>, objects
input_range_construct_test() : range<T>(60) {}
void run() const {
T x(test::input_iterator(this->values.begin()),
test::input_iterator(this->values.end()),
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
begin = this->values.begin(), end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end),
0, hash, equal_to, allocator);
}
};

View File

@ -10,7 +10,6 @@
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/input_iterator.hpp"
#include <boost/utility.hpp>
#include <cmath>

View File

@ -7,7 +7,8 @@
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
#include <boost/config.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>
namespace test
{
@ -16,7 +17,7 @@ namespace test
{
typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type;
proxy(value_type const& v) : v_(v) {}
explicit proxy(value_type const& v) : v_(v) {}
proxy(proxy const& x) : v_(x.v_) {}
operator value_type const&() const { return v_; }
@ -27,22 +28,44 @@ namespace test
template <class Iterator>
struct input_iterator_adaptor
: boost::iterator_adaptor<
input_iterator_adaptor<Iterator>, Iterator,
boost::use_default, std::input_iterator_tag,
proxy<Iterator> >
: public boost::iterator<
std::input_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator>
>
{
typedef boost::iterator_adaptor<
input_iterator_adaptor<Iterator>, Iterator,
boost::use_default, std::input_iterator_tag,
proxy<Iterator> > base;
explicit input_iterator_adaptor(Iterator it = Iterator())
: base(it) {}
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
input_iterator_adaptor()
: base_() {}
explicit input_iterator_adaptor(Iterator& it)
: base_(&it) {}
proxy<Iterator> operator*() const {
return proxy<Iterator>(**base_);
}
value_type* operator->() const {
return &**base_;
}
input_iterator_adaptor& operator++() {
++*base_; return *this;
}
//input_iterator_adaptor operator++(int) {
//}
bool operator==(input_iterator_adaptor const& x) const {
return *base_ == *x.base_;
}
bool operator!=(input_iterator_adaptor const& x) const {
return *base_ != *x.base_;
}
private:
Iterator* base_;
};
template <class Iterator>
input_iterator_adaptor<Iterator> input_iterator(Iterator it)
input_iterator_adaptor<Iterator> input_iterator(Iterator& it)
{
return input_iterator_adaptor<Iterator>(it);
}

View File

@ -245,8 +245,12 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
std::cerr<<"Construct 8 - from input iterator\n";
{
test::random_values<T> v(100, generator);
T x(test::input_iterator(v.begin()), test::input_iterator(v.end()), 0, hf1, eq1);
T y(test::input_iterator(x.begin()), test::input_iterator(x.end()), 0, hf2, eq2);
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
v_begin = v.begin(), v_end = v.end();
T x(test::input_iterator(v_begin), test::input_iterator(v_end), 0, hf1, eq1);
BOOST_DEDUCED_TYPENAME T::const_iterator
x_begin = x.begin(), x_end = x.end();
T y(test::input_iterator(x_begin), test::input_iterator(x_end), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);

View File

@ -8,35 +8,129 @@
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
namespace x
{
struct D { boost::unordered_map<D, D> x; };
}
namespace test
{
// Declare, but don't define some types.
struct value;
struct hash;
struct equals;
template <class T>
struct malloc_allocator;
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals, malloc_allocator<std::pair<value const, value> > > map;
typedef boost::unordered_multimap<value, value, hash, equals, malloc_allocator<std::pair<value const, value> > > multimap;
typedef boost::unordered_set<value, hash, equals, malloc_allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals, malloc_allocator<value> > multiset;
struct value {};
struct hash { std::size_t operator()(value const&) const { return 0; } };
struct equals { bool operator()(value const&, value const&) const { return true; } };
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
struct hash {
template <typename T>
std::size_t operator()(T const&) const { return 0; }
};
struct equals {
template <typename T>
bool operator()(T const&, T const&) const { return true; }
};
}
#include "../helpers/allocator.hpp"
int main() {
namespace test
{
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the moment.
struct struct1 {
boost::unordered_map<struct1, struct1, hash, equals, malloc_allocator<std::pair<struct1 const, struct1> > > x;
};
struct struct2 {
boost::unordered_multimap<struct2, struct2, hash, equals, malloc_allocator<std::pair<struct2 const, struct2> > > x;
};
struct struct3 {
boost::unordered_set<struct3, hash, equals, malloc_allocator<struct3> > x;
};
struct struct4 {
boost::unordered_multiset<struct4, hash, equals, malloc_allocator<struct4> > x;
};
// Now define the value type.
struct value {};
// Create some instances.
test::map m1;
test::multimap m2;
test::set s1;
test::multiset s2;
test::struct1 c1;
test::struct2 c2;
test::struct3 c3;
test::struct4 c4;
// Now declare, but don't define, the operators required for comparing elements.
std::size_t hash_value(value const&);
bool operator==(value const&, value const&);
std::size_t hash_value(struct1 const&);
std::size_t hash_value(struct2 const&);
std::size_t hash_value(struct3 const&);
std::size_t hash_value(struct4 const&);
test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
s2.insert(x);
bool operator==(struct1 const&, struct1 const&);
bool operator==(struct2 const&, struct2 const&);
bool operator==(struct3 const&, struct3 const&);
bool operator==(struct4 const&, struct4 const&);
// And finally use these
void use_types()
{
test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
s2.insert(x);
c1.x.insert(std::make_pair(c1, c1));
c2.x.insert(std::make_pair(c2, c2));
c3.x.insert(c3);
c4.x.insert(c4);
}
// And finally define the operators required for comparing elements.
std::size_t hash_value(value const&) { return 0; }
bool operator==(value const&, value const&) { return true; }
std::size_t hash_value(struct1 const&) { return 0; }
std::size_t hash_value(struct2 const&) { return 0; }
std::size_t hash_value(struct3 const&) { return 0; }
std::size_t hash_value(struct4 const&) { return 0; }
bool operator==(struct1 const&, struct1 const&) { return true; }
bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; }
}
int main() {
// This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring.
test::use_types();
}

View File

@ -213,7 +213,9 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
X x;
test::random_values<X> v(1000, generator);
x.insert(test::input_iterator(v.begin()), test::input_iterator(v.end()));
BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
begin = v.begin(), end = v.end();
x.insert(test::input_iterator(begin), test::input_iterator(end));
test::check_container(x, v);
test::check_equivalent_keys(x);

View File

@ -13,6 +13,15 @@ void foo(boost::unordered_set<int>& x1,
boost::unordered_multiset<int>& x3,
boost::unordered_multimap<int, int>& x4)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy {
boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4;
};
#endif
x1.insert(1);
x2[2] = 2;
x3.insert(3);