From a7546e298e0663538e74b6d588445d819070ce44 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 2 Nov 2016 07:30:41 +0000 Subject: [PATCH 1/4] Support 10 arguments in emplace_args Which was the intent, but only supported up to 9 arguments. I doubt this will make much of a difference. --- include/boost/unordered/detail/allocate.hpp | 3 +- test/Jamfile.v2 | 1 + test/helpers/count.hpp | 12 +- test/unordered/emplace_tests.cpp | 436 ++++++++++++++++++++ 4 files changed, 448 insertions(+), 4 deletions(-) create mode 100644 test/unordered/emplace_tests.cpp diff --git a/include/boost/unordered/detail/allocate.hpp b/include/boost/unordered/detail/allocate.hpp index 2d9cf4b6..8e4f8694 100644 --- a/include/boost/unordered/detail/allocate.hpp +++ b/include/boost/unordered/detail/allocate.hpp @@ -52,7 +52,8 @@ // will be default-initialized. #endif -#define BOOST_UNORDERED_EMPLACE_LIMIT 10 +// Maximum number of arguments supported by emplace + 1. +#define BOOST_UNORDERED_EMPLACE_LIMIT 11 namespace boost { namespace unordered { namespace detail { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7cfa8d71..5cf879c0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -43,6 +43,7 @@ test-suite unordered [ run unordered/insert_tests.cpp ] [ run unordered/insert_stable_tests.cpp ] [ run unordered/insert_hint_tests.cpp ] + [ run unordered/emplace_tests.cpp ] [ run unordered/unnecessary_copy_tests.cpp ] [ run unordered/erase_tests.cpp ] [ run unordered/erase_equiv_tests.cpp ] diff --git a/test/helpers/count.hpp b/test/helpers/count.hpp index b81b7e2b..dfb34e61 100644 --- a/test/helpers/count.hpp +++ b/test/helpers/count.hpp @@ -69,10 +69,16 @@ namespace test { }; struct check_instances { - int instances; + int instances_; + int constructions_; - check_instances() : instances(global_object_count.instances) {} - ~check_instances() { BOOST_TEST(global_object_count.instances == instances); } + check_instances() : + instances_(global_object_count.instances), + constructions_(global_object_count.constructions) {} + ~check_instances() { BOOST_TEST(global_object_count.instances == instances_); } + + int instances() const { return global_object_count.instances - instances_; } + int constructions() const { return global_object_count.constructions - constructions_; } }; } diff --git a/test/unordered/emplace_tests.cpp b/test/unordered/emplace_tests.cpp new file mode 100644 index 00000000..c08adc0b --- /dev/null +++ b/test/unordered/emplace_tests.cpp @@ -0,0 +1,436 @@ +// +// Copyright 2016 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) + +#include "../helpers/prefix.hpp" +#include +#include +#include "../helpers/postfix.hpp" + +#include +#include "../helpers/test.hpp" +#include "../helpers/count.hpp" +#include + + +// Test that various emplace methods work with different numbers of +// arguments. + +namespace emplace_tests { + // Constructible with 2 to 10 arguments + struct emplace_value : private test::counted_object { + typedef int A0; + typedef std::string A1; + typedef char A2; + typedef int A3; + typedef int A4; + typedef int A5; + typedef int A6; + typedef int A7; + typedef int A8; + typedef int A9; + + int arg_count; + + A0 a0; + A1 a1; + A2 a2; + A3 a3; + A4 a4; + A5 a5; + A6 a6; + A7 a7; + A8 a8; + A9 a9; + + emplace_value( + A0 const& b0, A1 const& b1) : + arg_count(2), + a0(b0), a1(b1) {} + + emplace_value( + A0 const& b0, A1 const& b1, A2 const& b2) : + arg_count(3), + a0(b0), a1(b1), a2(b2) {} + + emplace_value( + A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3) : + arg_count(4), + a0(b0), a1(b1), a2(b2), a3(b3) {} + + emplace_value( + A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, + A4 const& b4) : + arg_count(5), + a0(b0), a1(b1), a2(b2), a3(b3), a4(b4) {} + + emplace_value( + A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, + A4 const& b4, A5 const& b5) : + arg_count(6), + a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), + a5(b5) {} + + emplace_value( + A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, + A4 const& b4, A5 const& b5, A6 const& b6) : + arg_count(7), + a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), + a5(b5), a6(b6) {} + + emplace_value( + A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, + A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7) : + arg_count(8), + a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), + a5(b5), a6(b6), a7(b7) {} + + emplace_value( + A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, + A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, + A8 const& b8) : + arg_count(9), + a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), + a5(b5), a6(b6), a7(b7), a8(b8) {} + + emplace_value( + A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, + A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, + A8 const& b8, A9 const& b9) : + arg_count(10), + a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), + a5(b5), a6(b6), a7(b7), a8(b8), a9(b9) {} + + + friend std::size_t hash_value(emplace_value const& x) { + std::size_t r1 = 23894278u; + if (x.arg_count >= 1) boost::hash_combine(r1, x.a0); + if (x.arg_count >= 2) boost::hash_combine(r1, x.a1); + if (x.arg_count >= 3) boost::hash_combine(r1, x.a2); + if (x.arg_count >= 4) boost::hash_combine(r1, x.a3); + if (x.arg_count >= 5) boost::hash_combine(r1, x.a4); + if (x.arg_count >= 6) boost::hash_combine(r1, x.a5); + if (x.arg_count >= 7) boost::hash_combine(r1, x.a6); + if (x.arg_count >= 8) boost::hash_combine(r1, x.a7); + if (x.arg_count >= 9) boost::hash_combine(r1, x.a8); + if (x.arg_count >= 10) boost::hash_combine(r1, x.a9); + return r1; + } + + friend bool operator==(emplace_value const& x, emplace_value const& y) { + if (x.arg_count != y.arg_count) { return false; } + if (x.arg_count >= 1 && x.a0 != y.a0) { return false; } + if (x.arg_count >= 2 && x.a1 != y.a1) { return false; } + if (x.arg_count >= 3 && x.a2 != y.a2) { return false; } + if (x.arg_count >= 4 && x.a3 != y.a3) { return false; } + if (x.arg_count >= 5 && x.a4 != y.a4) { return false; } + if (x.arg_count >= 6 && x.a5 != y.a5) { return false; } + if (x.arg_count >= 7 && x.a6 != y.a6) { return false; } + if (x.arg_count >= 8 && x.a7 != y.a7) { return false; } + if (x.arg_count >= 9 && x.a8 != y.a8) { return false; } + if (x.arg_count >= 10 && x.a9 != y.a9) { return false; } + return true; + } + private: + emplace_value(); + emplace_value(emplace_value const&); + }; + + UNORDERED_AUTO_TEST(emplace_set) { + test::check_instances check_; + + typedef boost::unordered_set > container; + typedef container::iterator iterator; + typedef std::pair return_type; + container x(10); + iterator i1; + return_type r1,r2; + + // 2 args + + emplace_value v1(10, "x"); + r1 = x.emplace(10, std::string("x")); + BOOST_TEST_EQ(x.size(), 1u); + BOOST_TEST(r1.second); + BOOST_TEST(*r1.first == v1); + BOOST_TEST(r1.first == x.find(v1)); + BOOST_TEST_EQ(check_.instances(), 2); + BOOST_TEST_EQ(check_.constructions(), 2); + + // 3 args + + emplace_value v2(3, "foo", 'a'); + r1 = x.emplace(3, "foo", 'a'); + BOOST_TEST_EQ(x.size(), 2u); + BOOST_TEST(r1.second); + BOOST_TEST(*r1.first == v2); + BOOST_TEST(r1.first == x.find(v2)); + BOOST_TEST_EQ(check_.instances(), 4); + BOOST_TEST_EQ(check_.constructions(), 4); + + // 7 args with hint + duplicate + + emplace_value v3(25, "something", 'z', 4, 5, 6, 7); + i1 = x.emplace_hint(r1.first, 25, "something", 'z', 4, 5, 6, 7); + BOOST_TEST_EQ(x.size(), 3u); + BOOST_TEST(*i1 == v3); + BOOST_TEST(i1 == x.find(v3)); + BOOST_TEST_EQ(check_.instances(), 6); + BOOST_TEST_EQ(check_.constructions(), 6); + + r2 = x.emplace(25, "something", 'z', 4, 5, 6, 7); + BOOST_TEST_EQ(x.size(), 3u); + BOOST_TEST(!r2.second); + BOOST_TEST(i1 == r2.first); + // The container has to construct an object in order to check + // whether it can emplace, so there's an extra cosntruction + // here. + BOOST_TEST_EQ(check_.instances(), 6); + BOOST_TEST_EQ(check_.constructions(), 7); + + // 10 args + hint duplicate + + std::string s1; + emplace_value v4(10, s1, 'a', 4, 5, 6, 7, 8, 9, 10); + r1 = x.emplace(10, s1, 'a', 4, 5, 6, 7, 8, 9, 10); + BOOST_TEST_EQ(x.size(), 4u); + BOOST_TEST(r1.second); + BOOST_TEST(*r1.first == v4); + BOOST_TEST(r1.first == x.find(v4)); + BOOST_TEST_EQ(check_.instances(), 8); + BOOST_TEST_EQ(check_.constructions(), 9); + + BOOST_TEST(r1.first == + x.emplace_hint(r1.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10)); + BOOST_TEST(r1.first == + x.emplace_hint(r2.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10)); + BOOST_TEST(r1.first == + x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10)); + BOOST_TEST_EQ(check_.instances(), 8); + BOOST_TEST_EQ(check_.constructions(), 12); + + BOOST_TEST_EQ(x.size(), 4u); + BOOST_TEST(x.count(v1) == 1); + BOOST_TEST(x.count(v2) == 1); + BOOST_TEST(x.count(v3) == 1); + BOOST_TEST(x.count(v4) == 1); + } + + UNORDERED_AUTO_TEST(emplace_multiset) { + test::check_instances check_; + + typedef boost::unordered_multiset > container; + typedef container::iterator iterator; + container x(10); + iterator i1, i2; + + // 2 args. + + emplace_value v1(10, "x"); + i1 = x.emplace(10, std::string("x")); + BOOST_TEST_EQ(x.size(), 1u); + BOOST_TEST(i1 == x.find(v1)); + BOOST_TEST_EQ(check_.instances(), 2); + BOOST_TEST_EQ(check_.constructions(), 2); + + // 4 args + duplicate + + emplace_value v2(4, "foo", 'a', 15); + i1 = x.emplace(4, "foo", 'a', 15); + BOOST_TEST_EQ(x.size(), 2u); + BOOST_TEST(i1 == x.find(v2)); + BOOST_TEST_EQ(check_.instances(), 4); + BOOST_TEST_EQ(check_.constructions(), 4); + + i2 = x.emplace(4, "foo", 'a', 15); + BOOST_TEST_EQ(x.size(), 3u); + BOOST_TEST(i1 != i2); + BOOST_TEST(*i1 == *i2); + BOOST_TEST(x.count(*i1) == 2); + BOOST_TEST_EQ(check_.instances(), 5); + BOOST_TEST_EQ(check_.constructions(), 5); + + // 7 args + duplicate using hint. + + emplace_value v3(7, "", 'z', 4, 5, 6, 7); + i1 = x.emplace(7, "", 'z', 4, 5, 6, 7); + BOOST_TEST_EQ(x.size(), 4u); + BOOST_TEST_EQ(i1->a2, 'z'); + BOOST_TEST(x.count(*i1) == 1); + BOOST_TEST(i1 == x.find(v3)); + BOOST_TEST_EQ(check_.instances(), 7); + BOOST_TEST_EQ(check_.constructions(), 7); + + i2 = x.emplace_hint(i1, 7, "", 'z', 4, 5, 6, 7); + BOOST_TEST_EQ(x.size(), 5u); + BOOST_TEST(*i1 == *i2); + BOOST_TEST(i1 != i2); + BOOST_TEST(x.count(*i1) == 2); + BOOST_TEST_EQ(check_.instances(), 8); + BOOST_TEST_EQ(check_.constructions(), 8); + + // 10 args with bad hint + duplicate + + emplace_value v4(10, "", 'a', 4, 5, 6, 7, 8, 9, 10); + i1 = x.emplace_hint(i2, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10); + BOOST_TEST_EQ(x.size(), 6u); + BOOST_TEST_EQ(i1->arg_count, 10); + BOOST_TEST(i1 == x.find(v4)); + BOOST_TEST_EQ(check_.instances(), 10); + BOOST_TEST_EQ(check_.constructions(), 10); + + i2 = x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10); + BOOST_TEST_EQ(x.size(), 7u); + BOOST_TEST(*i1 == *i2); + BOOST_TEST(i1 != i2); + BOOST_TEST(x.count(*i1) == 2); + BOOST_TEST_EQ(check_.instances(), 11); + BOOST_TEST_EQ(check_.constructions(), 11); + + BOOST_TEST_EQ(x.count(v1), 1u); + BOOST_TEST_EQ(x.count(v2), 2u); + BOOST_TEST_EQ(x.count(v3), 2u); + } + + UNORDERED_AUTO_TEST(emplace_map) { + test::check_instances check_; + + typedef boost::unordered_map > container; + typedef container::iterator iterator; + typedef std::pair return_type; + container x(10); + return_type r1, r2; + + // 5/8 args + duplicate + + emplace_value k1(5, "", 'b', 4, 5); + emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8); + r1 = x.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(5, "", 'b', 4, 5), + boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); + BOOST_TEST_EQ(x.size(), 1u); + BOOST_TEST(r1.second); + BOOST_TEST(x.find(k1) == r1.first); + BOOST_TEST(x.find(k1)->second == m1); + BOOST_TEST_EQ(check_.instances(), 4); + BOOST_TEST_EQ(check_.constructions(), 4); + + r2 = x.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(5, "", 'b', 4, 5), + boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); + BOOST_TEST_EQ(x.size(), 1u); + BOOST_TEST(!r2.second); + BOOST_TEST(r1.first == r2.first); + BOOST_TEST(x.find(k1)->second == m1); + BOOST_TEST_EQ(check_.instances(), 4); + // constructions could possibly be 5 if the implementation only + // constructed the key. + BOOST_TEST_EQ(check_.constructions(), 6); + + // 9/3 args + duplicates with hints, different mapped value. + + emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9); + emplace_value m2(3, "aaa", 'm'); + r1 = x.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), + boost::make_tuple(3, "aaa", 'm')); + BOOST_TEST_EQ(x.size(), 2u); + BOOST_TEST(r1.second); + BOOST_TEST(r1.first->first.arg_count == 9); + BOOST_TEST(r1.first->second.arg_count == 3); + BOOST_TEST(x.find(k2) == r1.first); + BOOST_TEST(x.find(k2)->second == m2); + BOOST_TEST_EQ(check_.instances(), 8); + BOOST_TEST_EQ(check_.constructions(), 10); + + BOOST_TEST(r1.first == x.emplace_hint(r1.first, + boost::unordered::piecewise_construct, + boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), + boost::make_tuple(15, "jkjk"))); + BOOST_TEST(r1.first == x.emplace_hint(r2.first, + boost::unordered::piecewise_construct, + boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), + boost::make_tuple(275, "xxx", 'm', 6))); + BOOST_TEST(r1.first == x.emplace_hint(x.end(), + boost::unordered::piecewise_construct, + boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), + boost::make_tuple(-10, "blah blah", '\0'))); + BOOST_TEST_EQ(x.size(), 2u); + BOOST_TEST(x.find(k2)->second == m2); + BOOST_TEST_EQ(check_.instances(), 8); + BOOST_TEST_EQ(check_.constructions(), 16); + } + + UNORDERED_AUTO_TEST(emplace_multimap) { + test::check_instances check_; + + typedef boost::unordered_multimap > container; + typedef container::iterator iterator; + container x(10); + iterator i1, i2, i3, i4; + + // 5/8 args + duplicate + + emplace_value k1(5, "", 'b', 4, 5); + emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8); + i1 = x.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(5, "", 'b', 4, 5), + boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); + BOOST_TEST_EQ(x.size(), 1u); + BOOST_TEST(x.find(k1) == i1); + BOOST_TEST(x.find(k1)->second == m1); + BOOST_TEST_EQ(check_.instances(), 4); + BOOST_TEST_EQ(check_.constructions(), 4); + + emplace_value m1a(8, "xxx", 'z', 4, 5, 6, 7, 8); + i2 = x.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(5, "", 'b', 4, 5), + boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); + BOOST_TEST_EQ(x.size(), 2u); + BOOST_TEST(i1 != i2); + BOOST_TEST(i1->second == m1); + BOOST_TEST(i2->second == m1a); + BOOST_TEST_EQ(check_.instances(), 7); + BOOST_TEST_EQ(check_.constructions(), 7); + + // 9/3 args + duplicates with hints, different mapped value. + + emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9); + emplace_value m2(3, "aaa", 'm'); + i1 = x.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), + boost::make_tuple(3, "aaa", 'm')); + BOOST_TEST_EQ(x.size(), 3u); + BOOST_TEST(i1->first.arg_count == 9); + BOOST_TEST(i1->second.arg_count == 3); + BOOST_TEST_EQ(check_.instances(), 11); + BOOST_TEST_EQ(check_.constructions(), 11); + + emplace_value m2a(15, "jkjk"); + i2 = x.emplace_hint(i2, + boost::unordered::piecewise_construct, + boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), + boost::make_tuple(15, "jkjk")); + emplace_value m2b(275, "xxx", 'm', 6); + i3 = x.emplace_hint(i1, + boost::unordered::piecewise_construct, + boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), + boost::make_tuple(275, "xxx", 'm', 6)); + emplace_value m2c(-10, "blah blah", '\0'); + i4 = x.emplace_hint(x.end(), + boost::unordered::piecewise_construct, + boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), + boost::make_tuple(-10, "blah blah", '\0')); + BOOST_TEST_EQ(x.size(), 6u); + BOOST_TEST(x.find(k2)->second == m2); + BOOST_TEST_EQ(check_.instances(), 20); + BOOST_TEST_EQ(check_.constructions(), 20); + } +} + +RUN_TESTS() From 3db4654b44f03d6ae55f9f6038d1f145ee645932 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 6 Nov 2016 10:19:17 +0000 Subject: [PATCH 2/4] Remove unary/binary_function from examples/documentation They are being removed from the standard in C++17, and were never really required. --- doc/src_code/dictionary.cpp | 2 -- doc/src_code/point1.cpp | 1 - examples/case_insensitive.hpp | 2 -- 3 files changed, 5 deletions(-) diff --git a/doc/src_code/dictionary.cpp b/doc/src_code/dictionary.cpp index 1f8ead92..dece3089 100644 --- a/doc/src_code/dictionary.cpp +++ b/doc/src_code/dictionary.cpp @@ -10,7 +10,6 @@ //[case_insensitive_functions struct iequal_to - : std::binary_function { bool operator()(std::string const& x, std::string const& y) const @@ -20,7 +19,6 @@ }; struct ihash - : std::unary_function { std::size_t operator()(std::string const& x) const { diff --git a/doc/src_code/point1.cpp b/doc/src_code/point1.cpp index 0d17c1f5..dd562264 100644 --- a/doc/src_code/point1.cpp +++ b/doc/src_code/point1.cpp @@ -18,7 +18,6 @@ } struct point_hash - : std::unary_function { std::size_t operator()(point const& p) const { diff --git a/examples/case_insensitive.hpp b/examples/case_insensitive.hpp index 0204a221..83a388d8 100644 --- a/examples/case_insensitive.hpp +++ b/examples/case_insensitive.hpp @@ -19,7 +19,6 @@ namespace hash_examples { struct iequal_to - : std::binary_function { iequal_to() {} explicit iequal_to(std::locale const& l) : locale_(l) {} @@ -34,7 +33,6 @@ namespace hash_examples }; struct ihash - : std::unary_function { ihash() {} explicit ihash(std::locale const& l) : locale_(l) {} From 33f701dd090a61a82bf1fbe2edf3d37495dc9e8a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 21 Nov 2016 10:24:51 +0000 Subject: [PATCH 3/4] Fix assigning hash/key equality functions for empty containers --- include/boost/unordered/detail/table.hpp | 5 ++++- test/unordered/assign_tests.cpp | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 9657c763..1092d31f 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -589,7 +589,10 @@ namespace boost { namespace unordered { namespace detail { mlf_ = x.mlf_; recalculate_max_load(); - if (!size_ && !x.size_) return; + if (!size_ && !x.size_) { + new_func_this.commit(); + return; + } if (x.size_ >= max_load_) { create_buckets(min_buckets_for_size(x.size_)); diff --git a/test/unordered/assign_tests.cpp b/test/unordered/assign_tests.cpp index aa0f579f..0e2f6fdd 100644 --- a/test/unordered/assign_tests.cpp +++ b/test/unordered/assign_tests.cpp @@ -77,7 +77,21 @@ void assign_tests2(T*, test::random_generator generator) BOOST_DEDUCED_TYPENAME T::allocator_type al2(2); typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; - + + std::cerr<<"assign_tests2.0 - empty container\n"; + { + test::check_instances check_; + + T x1(0, hf1, eq1); + T x2(0, hf2, eq2); + x2 = x1; + BOOST_TEST(test::equivalent(x1.hash_function(), hf1)); + BOOST_TEST(test::equivalent(x1.key_eq(), eq1)); + BOOST_TEST(test::equivalent(x2.hash_function(), hf1)); + BOOST_TEST(test::equivalent(x2.key_eq(), eq1)); + test::check_container(x1, x2); + } + std::cerr<<"assign_tests2.1\n"; { test::check_instances check_; From 03a597983e848ca1eb5fd45186a34bd56f1785e9 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 5 Dec 2016 22:48:00 +0000 Subject: [PATCH 4/4] Change log for last few fixes --- doc/changes.qbk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/changes.qbk b/doc/changes.qbk index 0353e292..506fe1fe 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -296,5 +296,11 @@ C++11 support has resulted in some breaking changes: * Better allocator support ([ticket 12459]). * Make the no argument constructors implicit. * Implement missing allocator aware constructors. +* Fix assigning the hash/key equality functions for empty containers. +* Remove unary/binary_function from the examples in the documentation. + They are removed in C++17. +* Support 10 constructor arguments in emplace. It was meant to support up to 10 + arguments, but an off by one error in the preprocessor code meant it only + supports up to 10. [endsect]