diff --git a/doc/changes.qbk b/doc/changes.qbk index 6d0f0260..d1b26254 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -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] diff --git a/include/boost/unordered/detail/util.hpp b/include/boost/unordered/detail/util.hpp index 1f592dd3..22b41583 100644 --- a/include/boost/unordered/detail/util.hpp +++ b/include/boost/unordered/detail/util.hpp @@ -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 x; }; +#endif boost::unordered_detail::destroy(&node_->value()); } diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index b0034116..ef649897 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -38,16 +38,16 @@ namespace boost { - template + template class unordered_map { public: - typedef Key key_type; - typedef std::pair value_type; + typedef K key_type; + typedef std::pair 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 types; typedef BOOST_DEDUCED_TYPENAME types::impl table; @@ -177,7 +177,7 @@ namespace boost } #else unordered_map(boost::unordered_detail::move_from< - unordered_map + unordered_map > 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 emplace(value_type const& v = value_type()) { return boost::unordered_detail::pair_cast( @@ -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==( + friend bool operator==( unordered_map const&, unordered_map const&); - friend bool operator!=( + friend bool operator!=( unordered_map const&, unordered_map const&); #endif }; // class template unordered_map @@ -522,6 +524,9 @@ namespace boost inline bool operator==(unordered_map const& m1, unordered_map const& m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_map x; }; +#endif return m1.table_.equals(m2.table_); } @@ -529,6 +534,9 @@ namespace boost inline bool operator!=(unordered_map const& m1, unordered_map const& m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_map x; }; +#endif return !m1.table_.equals(m2.table_); } @@ -536,20 +544,23 @@ namespace boost inline void swap(unordered_map &m1, unordered_map &m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_map x; }; +#endif m1.swap(m2); } - template + template class unordered_multimap { public: - typedef Key key_type; - typedef std::pair value_type; + typedef K key_type; + typedef std::pair 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 types; typedef BOOST_DEDUCED_TYPENAME types::impl table; @@ -680,7 +691,7 @@ namespace boost } #else unordered_multimap(boost::unordered_detail::move_from< - unordered_multimap + unordered_multimap > 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==( + friend bool operator==( unordered_multimap const&, unordered_multimap const&); - friend bool operator!=( + friend bool operator!=( unordered_multimap const&, unordered_multimap const&); #endif }; // class template unordered_multimap @@ -1010,6 +1022,9 @@ namespace boost inline bool operator==(unordered_multimap const& m1, unordered_multimap const& m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_multimap x; }; +#endif return m1.table_.equals(m2.table_); } @@ -1017,6 +1032,9 @@ namespace boost inline bool operator!=(unordered_multimap const& m1, unordered_multimap const& m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_multimap x; }; +#endif return !m1.table_.equals(m2.table_); } @@ -1024,6 +1042,9 @@ namespace boost inline void swap(unordered_multimap &m1, unordered_multimap &m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_multimap x; }; +#endif m1.swap(m2); } diff --git a/include/boost/unordered/unordered_map_fwd.hpp b/include/boost/unordered/unordered_map_fwd.hpp index bbd81627..5e9bb076 100644 --- a/include/boost/unordered/unordered_map_fwd.hpp +++ b/include/boost/unordered/unordered_map_fwd.hpp @@ -17,11 +17,11 @@ namespace boost { - template , - class Pred = std::equal_to, - class Alloc = std::allocator > > + class H = hash, + class P = std::equal_to, + class A = std::allocator > > class unordered_map; template bool operator==(unordered_map const&, @@ -33,11 +33,11 @@ namespace boost void swap(unordered_map&, unordered_map&); - template , - class Pred = std::equal_to, - class Alloc = std::allocator > > + class H = hash, + class P = std::equal_to, + class A = std::allocator > > class unordered_multimap; template bool operator==(unordered_multimap const&, diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 26c5090a..59843fd6 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -38,16 +38,16 @@ namespace boost { - template + template 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 types; typedef BOOST_DEDUCED_TYPENAME types::impl table; @@ -171,7 +171,7 @@ namespace boost } #else unordered_set(boost::unordered_detail::move_from< - unordered_set + unordered_set > other) : table_(other.source.table_, boost::unordered_detail::move_tag()) { @@ -478,9 +478,9 @@ namespace boost } #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582) - friend bool operator==( + friend bool operator==( unordered_set const&, unordered_set const&); - friend bool operator!=( + friend bool operator!=( unordered_set const&, unordered_set const&); #endif }; // class template unordered_set @@ -489,6 +489,9 @@ namespace boost inline bool operator==(unordered_set const& m1, unordered_set const& m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_set x; }; +#endif return m1.table_.equals(m2.table_); } @@ -496,6 +499,9 @@ namespace boost inline bool operator!=(unordered_set const& m1, unordered_set const& m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_set x; }; +#endif return !m1.table_.equals(m2.table_); } @@ -503,19 +509,22 @@ namespace boost inline void swap(unordered_set &m1, unordered_set &m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_set x; }; +#endif m1.swap(m2); } - template + template 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 types; typedef BOOST_DEDUCED_TYPENAME types::impl table; @@ -640,7 +649,7 @@ namespace boost } #else unordered_multiset(boost::unordered_detail::move_from< - unordered_multiset + unordered_multiset > other) : table_(other.source.table_, boost::unordered_detail::move_tag()) { @@ -943,9 +952,9 @@ namespace boost } #if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582) - friend bool operator==( + friend bool operator==( unordered_multiset const&, unordered_multiset const&); - friend bool operator!=( + friend bool operator!=( unordered_multiset const&, unordered_multiset const&); #endif }; // class template unordered_multiset @@ -954,6 +963,9 @@ namespace boost inline bool operator==(unordered_multiset const& m1, unordered_multiset const& m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_multiset x; }; +#endif return m1.table_.equals(m2.table_); } @@ -961,6 +973,9 @@ namespace boost inline bool operator!=(unordered_multiset const& m1, unordered_multiset const& m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_multiset x; }; +#endif return !m1.table_.equals(m2.table_); } @@ -968,6 +983,9 @@ namespace boost inline void swap(unordered_multiset &m1, unordered_multiset &m2) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { unordered_multiset x; }; +#endif m1.swap(m2); } diff --git a/include/boost/unordered/unordered_set_fwd.hpp b/include/boost/unordered/unordered_set_fwd.hpp index 6b3f74e7..8000eb14 100644 --- a/include/boost/unordered/unordered_set_fwd.hpp +++ b/include/boost/unordered/unordered_set_fwd.hpp @@ -17,10 +17,10 @@ namespace boost { - template , - class Pred = std::equal_to, - class Alloc = std::allocator > + template , + class P = std::equal_to, + class A = std::allocator > class unordered_set; template bool operator==(unordered_set const&, @@ -32,10 +32,10 @@ namespace boost void swap(unordered_set &m1, unordered_set &m2); - template , - class Pred = std::equal_to, - class Alloc = std::allocator > + template , + class P = std::equal_to, + class A = std::allocator > class unordered_multiset; template bool operator==(unordered_multiset const&, diff --git a/test/exception/constructor_exception_tests.cpp b/test/exception/constructor_exception_tests.cpp index 15ab68e4..1b95af7d 100644 --- a/test/exception/constructor_exception_tests.cpp +++ b/test/exception/constructor_exception_tests.cpp @@ -126,8 +126,9 @@ struct input_range_construct_test : public range, objects input_range_construct_test() : range(60) {} void run() const { - T x(test::input_iterator(this->values.begin()), - test::input_iterator(this->values.end()), + BOOST_DEDUCED_TYPENAME test::random_values::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); } }; diff --git a/test/exception/insert_exception_tests.cpp b/test/exception/insert_exception_tests.cpp index 69651d61..946fe036 100644 --- a/test/exception/insert_exception_tests.cpp +++ b/test/exception/insert_exception_tests.cpp @@ -10,7 +10,6 @@ #include "../helpers/random_values.hpp" #include "../helpers/invariants.hpp" #include "../helpers/strong.hpp" -#include "../helpers/input_iterator.hpp" #include #include diff --git a/test/helpers/input_iterator.hpp b/test/helpers/input_iterator.hpp index 9e962baa..873120cd 100644 --- a/test/helpers/input_iterator.hpp +++ b/test/helpers/input_iterator.hpp @@ -7,7 +7,8 @@ #define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER #include -#include +#include +#include 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 struct input_iterator_adaptor - : boost::iterator_adaptor< - input_iterator_adaptor, Iterator, - boost::use_default, std::input_iterator_tag, - proxy > + : public boost::iterator< + std::input_iterator_tag, + BOOST_DEDUCED_TYPENAME boost::iterator_value::type, + std::ptrdiff_t, + BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type, + proxy + > { - typedef boost::iterator_adaptor< - input_iterator_adaptor, Iterator, - boost::use_default, std::input_iterator_tag, - proxy > base; - - explicit input_iterator_adaptor(Iterator it = Iterator()) - : base(it) {} + typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type + value_type; + + input_iterator_adaptor() + : base_() {} + explicit input_iterator_adaptor(Iterator& it) + : base_(&it) {} + proxy operator*() const { + return proxy(**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 - input_iterator_adaptor input_iterator(Iterator it) + input_iterator_adaptor input_iterator(Iterator& it) { return input_iterator_adaptor(it); } diff --git a/test/unordered/constructor_tests.cpp b/test/unordered/constructor_tests.cpp index 2e866b1d..5ad411f0 100644 --- a/test/unordered/constructor_tests.cpp +++ b/test/unordered/constructor_tests.cpp @@ -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 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::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); diff --git a/test/unordered/incomplete_test.cpp b/test/unordered/incomplete_test.cpp index b1666c9e..a8bf784a 100644 --- a/test/unordered/incomplete_test.cpp +++ b/test/unordered/incomplete_test.cpp @@ -8,35 +8,129 @@ #include #include +namespace x +{ + struct D { boost::unordered_map x; }; +} + namespace test { + // Declare, but don't define some types. + struct value; struct hash; struct equals; template struct malloc_allocator; + + // Declare some instances typedef boost::unordered_map > > map; typedef boost::unordered_multimap > > multimap; typedef boost::unordered_set > set; typedef boost::unordered_multiset > 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 + std::size_t operator()(T const&) const { return 0; } + }; + + struct equals { + template + 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 > > x; + }; + struct struct2 { + boost::unordered_multimap > > x; + }; + struct struct3 { + boost::unordered_set > x; + }; + struct struct4 { + boost::unordered_multiset > 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(); } diff --git a/test/unordered/insert_tests.cpp b/test/unordered/insert_tests.cpp index 69d0e86d..49f133f2 100644 --- a/test/unordered/insert_tests.cpp +++ b/test/unordered/insert_tests.cpp @@ -213,7 +213,9 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato X x; test::random_values v(1000, generator); - x.insert(test::input_iterator(v.begin()), test::input_iterator(v.end())); + BOOST_DEDUCED_TYPENAME test::random_values::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); diff --git a/test/unordered/link_test_2.cpp b/test/unordered/link_test_2.cpp index abcf2130..ff6432de 100644 --- a/test/unordered/link_test_2.cpp +++ b/test/unordered/link_test_2.cpp @@ -13,6 +13,15 @@ void foo(boost::unordered_set& x1, boost::unordered_multiset& x3, boost::unordered_multimap& x4) { +#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) + struct dummy { + boost::unordered_set x1; + boost::unordered_map x2; + boost::unordered_multiset x3; + boost::unordered_multimap x4; + }; +#endif + x1.insert(1); x2[2] = 2; x3.insert(3);