summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/unordered
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/unordered
parentInitial commit. (diff)
downloadceph-upstream.tar.xz
ceph-upstream.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/unordered')
-rw-r--r--src/boost/libs/unordered/_clang-format38
-rw-r--r--src/boost/libs/unordered/ci/download-boost-snapshot.py66
-rw-r--r--src/boost/libs/unordered/examples/case_insensitive.hpp58
-rw-r--r--src/boost/libs/unordered/examples/case_insensitive_test.cpp82
-rw-r--r--src/boost/libs/unordered/examples/fnv1.hpp69
-rw-r--r--src/boost/libs/unordered/index.html16
-rw-r--r--src/boost/libs/unordered/meta/explicit-failures-markup.xml44
-rw-r--r--src/boost/libs/unordered/meta/libraries.json17
-rw-r--r--src/boost/libs/unordered/test/Jamfile.v297
-rw-r--r--src/boost/libs/unordered/test/exception/assign_exception_tests.cpp185
-rw-r--r--src/boost/libs/unordered/test/exception/constructor_exception_tests.cpp212
-rw-r--r--src/boost/libs/unordered/test/exception/containers.hpp44
-rw-r--r--src/boost/libs/unordered/test/exception/copy_exception_tests.cpp110
-rw-r--r--src/boost/libs/unordered/test/exception/erase_exception_tests.cpp55
-rw-r--r--src/boost/libs/unordered/test/exception/insert_exception_tests.cpp416
-rw-r--r--src/boost/libs/unordered/test/exception/merge_exception_tests.cpp108
-rw-r--r--src/boost/libs/unordered/test/exception/move_assign_exception_tests.cpp132
-rw-r--r--src/boost/libs/unordered/test/exception/rehash_exception_tests.cpp133
-rw-r--r--src/boost/libs/unordered/test/exception/swap_exception_tests.cpp145
-rw-r--r--src/boost/libs/unordered/test/helpers/check_return_type.hpp33
-rw-r--r--src/boost/libs/unordered/test/helpers/count.hpp89
-rw-r--r--src/boost/libs/unordered/test/helpers/equivalent.hpp96
-rw-r--r--src/boost/libs/unordered/test/helpers/exception_test.hpp348
-rw-r--r--src/boost/libs/unordered/test/helpers/fwd.hpp32
-rw-r--r--src/boost/libs/unordered/test/helpers/generators.hpp93
-rw-r--r--src/boost/libs/unordered/test/helpers/helpers.hpp56
-rw-r--r--src/boost/libs/unordered/test/helpers/input_iterator.hpp165
-rw-r--r--src/boost/libs/unordered/test/helpers/invariants.hpp130
-rw-r--r--src/boost/libs/unordered/test/helpers/list.hpp327
-rw-r--r--src/boost/libs/unordered/test/helpers/memory.hpp189
-rw-r--r--src/boost/libs/unordered/test/helpers/metafunctions.hpp30
-rw-r--r--src/boost/libs/unordered/test/helpers/postfix.hpp10
-rw-r--r--src/boost/libs/unordered/test/helpers/prefix.hpp11
-rw-r--r--src/boost/libs/unordered/test/helpers/random_values.hpp109
-rw-r--r--src/boost/libs/unordered/test/helpers/strong.hpp42
-rw-r--r--src/boost/libs/unordered/test/helpers/test.hpp201
-rw-r--r--src/boost/libs/unordered/test/helpers/tracker.hpp138
-rw-r--r--src/boost/libs/unordered/test/objects/cxx11_allocator.hpp344
-rw-r--r--src/boost/libs/unordered/test/objects/exception.hpp752
-rw-r--r--src/boost/libs/unordered/test/objects/fwd.hpp17
-rw-r--r--src/boost/libs/unordered/test/objects/minimal.hpp627
-rw-r--r--src/boost/libs/unordered/test/objects/test.hpp700
-rw-r--r--src/boost/libs/unordered/test/unordered/allocator_traits.cpp288
-rw-r--r--src/boost/libs/unordered/test/unordered/assign_tests.cpp297
-rw-r--r--src/boost/libs/unordered/test/unordered/at_tests.cpp67
-rw-r--r--src/boost/libs/unordered/test/unordered/bucket_tests.cpp94
-rw-r--r--src/boost/libs/unordered/test/unordered/compile_map.cpp248
-rw-r--r--src/boost/libs/unordered/test/unordered/compile_set.cpp313
-rw-r--r--src/boost/libs/unordered/test/unordered/compile_tests.hpp913
-rw-r--r--src/boost/libs/unordered/test/unordered/constructor_tests.cpp446
-rw-r--r--src/boost/libs/unordered/test/unordered/copy_tests.cpp209
-rw-r--r--src/boost/libs/unordered/test/unordered/deduction_tests.cpp352
-rw-r--r--src/boost/libs/unordered/test/unordered/detail_tests.cpp101
-rw-r--r--src/boost/libs/unordered/test/unordered/emplace_tests.cpp514
-rw-r--r--src/boost/libs/unordered/test/unordered/equality_tests.cpp156
-rw-r--r--src/boost/libs/unordered/test/unordered/equivalent_keys_tests.cpp77
-rw-r--r--src/boost/libs/unordered/test/unordered/erase_equiv_tests.cpp217
-rw-r--r--src/boost/libs/unordered/test/unordered/erase_tests.cpp267
-rw-r--r--src/boost/libs/unordered/test/unordered/extract_tests.cpp133
-rw-r--r--src/boost/libs/unordered/test/unordered/find_tests.cpp157
-rw-r--r--src/boost/libs/unordered/test/unordered/fwd_map_test.cpp81
-rw-r--r--src/boost/libs/unordered/test/unordered/fwd_set_test.cpp106
-rw-r--r--src/boost/libs/unordered/test/unordered/incomplete_test.cpp173
-rw-r--r--src/boost/libs/unordered/test/unordered/insert_hint_tests.cpp121
-rw-r--r--src/boost/libs/unordered/test/unordered/insert_node_type_fail.cpp34
-rw-r--r--src/boost/libs/unordered/test/unordered/insert_stable_tests.cpp117
-rw-r--r--src/boost/libs/unordered/test/unordered/insert_tests.cpp1425
-rw-r--r--src/boost/libs/unordered/test/unordered/link_test_1.cpp26
-rw-r--r--src/boost/libs/unordered/test/unordered/link_test_2.cpp30
-rw-r--r--src/boost/libs/unordered/test/unordered/load_factor_tests.cpp97
-rw-r--r--src/boost/libs/unordered/test/unordered/merge_tests.cpp337
-rw-r--r--src/boost/libs/unordered/test/unordered/minimal_allocator.cpp92
-rw-r--r--src/boost/libs/unordered/test/unordered/move_tests.cpp372
-rw-r--r--src/boost/libs/unordered/test/unordered/node_handle_tests.cpp424
-rw-r--r--src/boost/libs/unordered/test/unordered/noexcept_tests.cpp320
-rw-r--r--src/boost/libs/unordered/test/unordered/rehash_tests.cpp229
-rw-r--r--src/boost/libs/unordered/test/unordered/simple_tests.cpp134
-rw-r--r--src/boost/libs/unordered/test/unordered/swap_tests.cpp211
-rw-r--r--src/boost/libs/unordered/test/unordered/unnecessary_copy_tests.cpp582
79 files changed, 16326 insertions, 0 deletions
diff --git a/src/boost/libs/unordered/_clang-format b/src/boost/libs/unordered/_clang-format
new file mode 100644
index 000000000..d892b414c
--- /dev/null
+++ b/src/boost/libs/unordered/_clang-format
@@ -0,0 +1,38 @@
+
+# Copyright 2017 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)
+
+# Using clang format 4.0
+# http://llvm.org/releases/4.0.0/tools/clang/docs/ClangFormatStyleOptions.html
+
+# Becuase you have to start somewhere.
+BasedOnStyle: LLVM
+
+# Basic settings
+ColumnLimit: 80
+NamespaceIndentation: All
+ContinuationIndentWidth: 2
+IndentWidth: 2
+UseTab: Never
+Language: Cpp
+Standard: Cpp03
+
+# Code layout
+AlignAfterOpenBracket: DontAlign
+AlignTrailingComments: true
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterNamespace: false
+ AfterClass: true
+ AfterStruct: true
+ AfterUnion: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterControlStatement: false
+ BeforeCatch: false
+ BeforeElse: false
+PointerAlignment: Left
+
+# Boost specific stuff
+ForEachMacros: [ BOOST_FOREACH, UNORDERED_AUTO_TEST ]
diff --git a/src/boost/libs/unordered/ci/download-boost-snapshot.py b/src/boost/libs/unordered/ci/download-boost-snapshot.py
new file mode 100644
index 000000000..a9d8ba98f
--- /dev/null
+++ b/src/boost/libs/unordered/ci/download-boost-snapshot.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+import urllib, os, os.path, sys, json, tarfile, zipfile, tempfile
+
+def download(snapshot):
+ if snapshot == 'stable':
+ # TODO: Default version/filename if not available?
+ downloads = [
+ "https://sourceforge.net/projects/boost/files/boost/%s/%s.tar.bz2/download" %
+ (os.environ['BOOST_VERSION'], os.environ['BOOST_FILENAME'])]
+ else:
+ json_response = urllib.urlopen('https://api.bintray.com/packages/boostorg/%s/snapshot/files' % (snapshot))
+ x = json.load(json_response)
+
+ extension_priorities = { '.bz2': 2, '.gz': 1, '.zip': 0 }
+ file_list = []
+ version_dates = {}
+ for file in x:
+ file_extension = os.path.splitext(file['path'])[1]
+ if (file_extension in extension_priorities):
+ file['priority'] = extension_priorities[file_extension]
+ file_list.append(file)
+ if not file['version'] in version_dates or file['created'] < version_dates[file['version']]:
+ version_dates[file['version']] = file['created']
+ file_list.sort(key=lambda x: (version_dates[x['version']], x['priority']), reverse=True)
+ downloads = ['http://dl.bintray.com/boostorg/%s/%s' % (snapshot, file['path']) for file in file_list]
+
+ filename = ''
+ for download_url in downloads:
+ try:
+ print "Downloading: " + download_url
+ (filename, headers) = urllib.urlretrieve(download_url)
+
+ print "Extracting: " + filename
+ dir = tempfile.mkdtemp()
+ extract(filename, dir)
+ os.remove(filename)
+ files = os.listdir(dir)
+ assert(len(files) == 1)
+ os.rename(os.path.join(dir, files[0]), 'boost')
+ return
+ except IOError:
+ print "Error opening URL: " + download_url
+
+def extract(filename, path = '.'):
+ if (filename.endswith(".gz")):
+ tar = tarfile.open(filename, "r:gz")
+ tar.extractall(path)
+ tar.close
+ elif (filename.endswith(".bz2")):
+ tar = tarfile.open(filename, "r:bz2")
+ tar.extractall(path)
+ tar.close
+ elif (filename.endswith(".zip")):
+ zip = zipfile.ZipFile(filename, "r")
+ zip.extractall(path)
+ zip.close
+ else:
+ assert False
+
+if len(sys.argv) == 1:
+ download('stable')
+elif len(sys.argv) == 2:
+ download(sys.argv[1])
+else:
+ print "Usage: %s [stable|branch-name]" % (sys.argv[0])
diff --git a/src/boost/libs/unordered/examples/case_insensitive.hpp b/src/boost/libs/unordered/examples/case_insensitive.hpp
new file mode 100644
index 000000000..83a388d87
--- /dev/null
+++ b/src/boost/libs/unordered/examples/case_insensitive.hpp
@@ -0,0 +1,58 @@
+
+// Copyright 2006-2009 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)
+
+// This file implements a locale aware case insenstive equality predicate and
+// hash function. Unfortunately it still falls short of full
+// internationalization as it only deals with a single character at a time
+// (some languages have tricky cases where the characters in an upper case
+// string don't have a one-to-one correspondence with the lower case version of
+// the text, eg. )
+
+#if !defined(BOOST_HASH_EXAMPLES_CASE_INSENSITIVE_HEADER)
+#define BOOST_HASH_EXAMPLES_CASE_INSENSITIVE_HEADER
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/functional/hash.hpp>
+
+namespace hash_examples
+{
+ struct iequal_to
+ {
+ iequal_to() {}
+ explicit iequal_to(std::locale const& l) : locale_(l) {}
+
+ template <typename String1, typename String2>
+ bool operator()(String1 const& x1, String2 const& x2) const
+ {
+ return boost::algorithm::iequals(x1, x2, locale_);
+ }
+ private:
+ std::locale locale_;
+ };
+
+ struct ihash
+ {
+ ihash() {}
+ explicit ihash(std::locale const& l) : locale_(l) {}
+
+ template <typename String>
+ std::size_t operator()(String const& x) const
+ {
+ std::size_t seed = 0;
+
+ for(typename String::const_iterator it = x.begin();
+ it != x.end(); ++it)
+ {
+ boost::hash_combine(seed, std::toupper(*it, locale_));
+ }
+
+ return seed;
+ }
+ private:
+ std::locale locale_;
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/examples/case_insensitive_test.cpp b/src/boost/libs/unordered/examples/case_insensitive_test.cpp
new file mode 100644
index 000000000..b717c1306
--- /dev/null
+++ b/src/boost/libs/unordered/examples/case_insensitive_test.cpp
@@ -0,0 +1,82 @@
+
+// Copyright 2006-2009 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 "./case_insensitive.hpp"
+#include <boost/core/lightweight_test.hpp>
+#include <boost/unordered_map.hpp>
+
+struct word_info {
+ int tag;
+ explicit word_info(int t = 0) : tag(t) {}
+};
+
+void test1() {
+ boost::unordered_map<std::string, word_info,
+ hash_examples::ihash, hash_examples::iequal_to> idictionary;
+
+ BOOST_TEST(idictionary.empty());
+
+ idictionary["one"] = word_info(1);
+ BOOST_TEST(idictionary.size() == 1);
+ BOOST_TEST(idictionary.find("ONE") != idictionary.end() &&
+ idictionary.find("ONE") == idictionary.find("one"));
+
+ idictionary.insert(std::make_pair("ONE", word_info(2)));
+ BOOST_TEST(idictionary.size() == 1);
+ BOOST_TEST(idictionary.find("ONE") != idictionary.end() &&
+ idictionary.find("ONE")->first == "one" &&
+ idictionary.find("ONE")->second.tag == 1);
+
+ idictionary["One"] = word_info(3);
+ BOOST_TEST(idictionary.size() == 1);
+ BOOST_TEST(idictionary.find("ONE") != idictionary.end() &&
+ idictionary.find("ONE")->first == "one" &&
+ idictionary.find("ONE")->second.tag == 3);
+
+ idictionary["two"] = word_info(4);
+ BOOST_TEST(idictionary.size() == 2);
+ BOOST_TEST(idictionary.find("two") != idictionary.end() &&
+ idictionary.find("TWO")->first == "two" &&
+ idictionary.find("Two")->second.tag == 4);
+
+
+}
+
+void test2() {
+ boost::unordered_map<std::wstring, word_info,
+ hash_examples::ihash, hash_examples::iequal_to> idictionary;
+
+ BOOST_TEST(idictionary.empty());
+
+ idictionary[L"one"] = word_info(1);
+ BOOST_TEST(idictionary.size() == 1);
+ BOOST_TEST(idictionary.find(L"ONE") != idictionary.end() &&
+ idictionary.find(L"ONE") == idictionary.find(L"one"));
+
+ idictionary.insert(std::make_pair(L"ONE", word_info(2)));
+ BOOST_TEST(idictionary.size() == 1);
+ BOOST_TEST(idictionary.find(L"ONE") != idictionary.end() &&
+ idictionary.find(L"ONE")->first == L"one" &&
+ idictionary.find(L"ONE")->second.tag == 1);
+
+ idictionary[L"One"] = word_info(3);
+ BOOST_TEST(idictionary.size() == 1);
+ BOOST_TEST(idictionary.find(L"ONE") != idictionary.end() &&
+ idictionary.find(L"ONE")->first == L"one" &&
+ idictionary.find(L"ONE")->second.tag == 3);
+
+ idictionary[L"two"] = word_info(4);
+ BOOST_TEST(idictionary.size() == 2);
+ BOOST_TEST(idictionary.find(L"two") != idictionary.end() &&
+ idictionary.find(L"TWO")->first == L"two" &&
+ idictionary.find(L"Two")->second.tag == 4);
+}
+
+int main() {
+ test1();
+ test2();
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/unordered/examples/fnv1.hpp b/src/boost/libs/unordered/examples/fnv1.hpp
new file mode 100644
index 000000000..3337d1365
--- /dev/null
+++ b/src/boost/libs/unordered/examples/fnv1.hpp
@@ -0,0 +1,69 @@
+
+// Copyright 2008-2009 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)
+
+// This code is also released into the public domain.
+
+// Algorithm from: http://www.isthe.com/chongo/tech/comp/fnv/
+
+#include <string>
+
+namespace hash
+{
+ template <std::size_t FnvPrime, std::size_t OffsetBasis>
+ struct basic_fnv_1
+ {
+ std::size_t operator()(std::string const& text) const
+ {
+ std::size_t hash = OffsetBasis;
+ for(std::string::const_iterator it = text.begin(), end = text.end();
+ it != end; ++it)
+ {
+ hash *= FnvPrime;
+ hash ^= *it;
+ }
+
+ return hash;
+ }
+ };
+
+ template <std::size_t FnvPrime, std::size_t OffsetBasis>
+ struct basic_fnv_1a
+ {
+ std::size_t operator()(std::string const& text) const
+ {
+ std::size_t hash = OffsetBasis;
+ for(std::string::const_iterator it = text.begin(), end = text.end();
+ it != end; ++it)
+ {
+ hash ^= *it;
+ hash *= FnvPrime;
+ }
+
+ return hash;
+ }
+ };
+
+ // For 32 bit machines:
+ const std::size_t fnv_prime = 16777619u;
+ const std::size_t fnv_offset_basis = 2166136261u;
+
+ // For 64 bit machines:
+ // const std::size_t fnv_prime = 1099511628211u;
+ // const std::size_t fnv_offset_basis = 14695981039346656037u;
+
+ // For 128 bit machines:
+ // const std::size_t fnv_prime = 309485009821345068724781401u;
+ // const std::size_t fnv_offset_basis =
+ // 275519064689413815358837431229664493455u;
+
+ // For 256 bit machines:
+ // const std::size_t fnv_prime =
+ // 374144419156711147060143317175368453031918731002211u;
+ // const std::size_t fnv_offset_basis =
+ // 100029257958052580907070968620625704837092796014241193945225284501741471925557u;
+
+ typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;
+ typedef basic_fnv_1a<fnv_prime, fnv_offset_basis> fnv_1a;
+}
diff --git a/src/boost/libs/unordered/index.html b/src/boost/libs/unordered/index.html
new file mode 100644
index 000000000..a752386cf
--- /dev/null
+++ b/src/boost/libs/unordered/index.html
@@ -0,0 +1,16 @@
+
+<!--
+Copyright 2005-2007 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)
+-->
+
+<html>
+<head>
+ <meta http-equiv="refresh" content="0; URL=../../doc/html/unordered.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+<a href="../../doc/html/unordered.html">../../doc/html/unordered.html</a>
+</body>
+</html>
diff --git a/src/boost/libs/unordered/meta/explicit-failures-markup.xml b/src/boost/libs/unordered/meta/explicit-failures-markup.xml
new file mode 100644
index 000000000..25a19e3df
--- /dev/null
+++ b/src/boost/libs/unordered/meta/explicit-failures-markup.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2017-2018 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)
+-->
+<explicit-failures-markup>
+ <!-- unordered -->
+ <library name="unordered">
+ <mark-expected-failures>
+ <test name="unnecessary_copy_tests"/>
+ <toolset name="borland-*"/>
+ <toolset name="sun-*"/>
+ <note author="Daniel James">
+ This tests whether inserting elements creates as few copies as I think
+ is possible. If this fails it just means that the container might be
+ a little inefficient.
+ </note>
+ </mark-expected-failures>
+
+ <mark-expected-failures>
+ <test name="compile_map_unordered_allocator"/>
+ <toolset name="msvc-7.1"/>
+ <note author="Daniel James">
+ This test fail because it's using unordered's internal
+ allocator traits, which doesn't work on Visual C++ 7.1.
+ It normally uses the one from Boost.Container by default.
+ </note>
+ </mark-expected-failures>
+
+ <mark-expected-failures>
+ <test name="noexcept_tests"/>
+ <toolset name="gcc-4.3c+"/>
+ <note author="Daniel James">
+ boost::is_nothrow_move_constructible and
+ boost::is_nothrow_move_assignable don't seem to work on this
+ compiler. I'd hope that anyone wanting noexcept support would
+ use a more recent compiler anyway.
+ </note>
+ </mark-expected-failures>
+ </library>
+</explicit-failures-markup>
+
diff --git a/src/boost/libs/unordered/meta/libraries.json b/src/boost/libs/unordered/meta/libraries.json
new file mode 100644
index 000000000..1cd5b6ce8
--- /dev/null
+++ b/src/boost/libs/unordered/meta/libraries.json
@@ -0,0 +1,17 @@
+{
+ "key": "unordered",
+ "name": "Unordered",
+ "authors": [
+ "Daniel James"
+ ],
+ "maintainers": [
+ "Daniel James <dnljms -at- gmail.com>"
+ ],
+ "description": "Unordered associative containers.",
+ "std": [
+ "tr1"
+ ],
+ "category": [
+ "Containers"
+ ]
+} \ No newline at end of file
diff --git a/src/boost/libs/unordered/test/Jamfile.v2 b/src/boost/libs/unordered/test/Jamfile.v2
new file mode 100644
index 000000000..67c31d989
--- /dev/null
+++ b/src/boost/libs/unordered/test/Jamfile.v2
@@ -0,0 +1,97 @@
+
+# Copyright 2006-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)
+
+import testing ;
+
+project unordered-test/unordered
+ : requirements
+ <warnings>all
+ <toolset>intel:<warnings>on
+ # Would be nice to define -Wundef, but I'm getting warnings from
+ # Boost.Preprocessor on trunk.
+ <toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
+ <toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
+ <toolset>clang:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
+ <toolset>msvc:<cxxflags>"/wd4494"
+ <toolset>gcc:<c++-template-depth>500
+ ;
+
+#alias framework : /boost/test//boost_unit_test_framework ;
+alias framework : ;
+
+test-suite unordered
+ :
+ [ run unordered/fwd_set_test.cpp ]
+ [ run unordered/fwd_map_test.cpp ]
+ [ run unordered/allocator_traits.cpp ]
+ [ run unordered/minimal_allocator.cpp ]
+ [ run unordered/compile_set.cpp ]
+ [ run unordered/compile_map.cpp ]
+ [ run unordered/compile_map.cpp : :
+ : <define>BOOST_UNORDERED_USE_ALLOCATOR_TRAITS=0
+ : compile_map_unordered_allocator ]
+ [ run unordered/noexcept_tests.cpp ]
+ [ run unordered/link_test_1.cpp unordered/link_test_2.cpp ]
+ [ run unordered/incomplete_test.cpp ]
+ [ run unordered/simple_tests.cpp ]
+ [ run unordered/equivalent_keys_tests.cpp ]
+ [ run unordered/constructor_tests.cpp ]
+ [ run unordered/copy_tests.cpp ]
+ [ run unordered/move_tests.cpp ]
+ [ run unordered/assign_tests.cpp ]
+ [ 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 : : : <define>BOOST_UNORDERED_SUPPRESS_DEPRECATED ]
+ [ run unordered/erase_equiv_tests.cpp ]
+ [ run unordered/extract_tests.cpp ]
+ [ run unordered/node_handle_tests.cpp ]
+ [ run unordered/merge_tests.cpp ]
+ [ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MAP : insert_node_type_fail_map ]
+ [ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MULTIMAP : insert_node_type_fail_multimap ]
+ [ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_SET : insert_node_type_fail_set ]
+ [ compile-fail unordered/insert_node_type_fail.cpp : <define>UNORDERED_TEST_MULTISET : insert_node_type_fail_multiset ]
+ [ run unordered/find_tests.cpp ]
+ [ run unordered/at_tests.cpp ]
+ [ run unordered/bucket_tests.cpp ]
+ [ run unordered/load_factor_tests.cpp ]
+ [ run unordered/rehash_tests.cpp ]
+ [ run unordered/equality_tests.cpp ]
+ [ run unordered/swap_tests.cpp ]
+ [ run unordered/detail_tests.cpp ]
+ [ run unordered/deduction_tests.cpp ]
+
+ [ run unordered/compile_set.cpp : :
+ : <define>BOOST_UNORDERED_USE_MOVE
+ : bmove_compile_set ]
+ [ run unordered/compile_map.cpp : :
+ : <define>BOOST_UNORDERED_USE_MOVE
+ : bmove_compile_map ]
+ [ run unordered/copy_tests.cpp : :
+ : <define>BOOST_UNORDERED_USE_MOVE
+ : bmove_copy ]
+ [ run unordered/move_tests.cpp : :
+ : <define>BOOST_UNORDERED_USE_MOVE
+ : bmove_move ]
+ [ run unordered/assign_tests.cpp : :
+ : <define>BOOST_UNORDERED_USE_MOVE
+ : bmove_assign ]
+ ;
+
+test-suite unordered-exception
+ :
+ [ run exception/constructor_exception_tests.cpp framework ]
+ [ run exception/copy_exception_tests.cpp framework ]
+ [ run exception/assign_exception_tests.cpp framework ]
+ [ run exception/move_assign_exception_tests.cpp framework ]
+ [ run exception/insert_exception_tests.cpp framework ]
+ [ run exception/erase_exception_tests.cpp framework ]
+ [ run exception/rehash_exception_tests.cpp framework ]
+ [ run exception/swap_exception_tests.cpp framework : : :
+ <define>BOOST_UNORDERED_SWAP_METHOD=2 ]
+ [ run exception/merge_exception_tests.cpp framework ]
+ ;
diff --git a/src/boost/libs/unordered/test/exception/assign_exception_tests.cpp b/src/boost/libs/unordered/test/exception/assign_exception_tests.cpp
new file mode 100644
index 000000000..c62bf8ab5
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/assign_exception_tests.cpp
@@ -0,0 +1,185 @@
+
+// Copyright 2006-2009 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 "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#endif
+
+test::seed_t initialize_seed(12847);
+
+template <class T> struct self_assign_base : public test::exception_base
+{
+ test::random_values<T> values;
+ self_assign_base(std::size_t count = 0) : values(count, test::limited_range)
+ {
+ }
+
+ typedef T data_type;
+ T init() const { return T(values.begin(), values.end()); }
+
+ void run(T& x) const
+ {
+ x = x;
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, values);
+ test::check_equivalent_keys(x);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
+ {
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct self_assign_test1 : self_assign_base<T>
+{
+};
+
+template <class T> struct self_assign_test2 : self_assign_base<T>
+{
+ self_assign_test2() : self_assign_base<T>(100) {}
+};
+
+template <class T> struct assign_base : public test::exception_base
+{
+ test::random_values<T> x_values, y_values;
+ T x, y;
+
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::allocator_type allocator_type;
+
+ assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
+ : x_values(), y_values(),
+ x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
+ y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
+ {
+ x.max_load_factor(mlf1);
+ y.max_load_factor(mlf2);
+ }
+
+ typedef T data_type;
+ T init() const { return T(x); }
+
+ void run(T& x1) const
+ {
+ x1 = y;
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x1, y_values);
+ test::check_equivalent_keys(x1);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
+ {
+ test::check_equivalent_keys(x1);
+
+ // If the container is empty at the point of the exception, the
+ // internal structure is hidden, this exposes it, at the cost of
+ // messing up the data.
+ if (x_values.size()) {
+ T& x2 = const_cast<T&>(x1);
+ x2.emplace(*x_values.begin());
+ test::check_equivalent_keys(x2);
+ }
+ }
+};
+
+template <class T> struct assign_values : assign_base<T>
+{
+ assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2,
+ test::random_generator gen = test::default_generator, float mlf1 = 1.0,
+ float mlf2 = 1.0)
+ : assign_base<T>(tag1, tag2, mlf1, mlf2)
+ {
+ this->x_values.fill(count1, gen);
+ this->y_values.fill(count2, gen);
+ this->x.insert(this->x_values.begin(), this->x_values.end());
+ this->y.insert(this->y_values.begin(), this->y_values.end());
+ }
+};
+
+template <class T> struct assign_test1 : assign_values<T>
+{
+ assign_test1() : assign_values<T>(0, 0, 0, 0) {}
+};
+
+template <class T> struct assign_test2 : assign_values<T>
+{
+ assign_test2() : assign_values<T>(60, 0, 0, 0) {}
+};
+
+template <class T> struct assign_test2a : assign_values<T>
+{
+ assign_test2a() : assign_values<T>(60, 0, 0, 0, test::limited_range) {}
+};
+
+template <class T> struct assign_test3 : assign_values<T>
+{
+ assign_test3() : assign_values<T>(0, 60, 0, 0) {}
+};
+
+template <class T> struct assign_test3a : assign_values<T>
+{
+ assign_test3a() : assign_values<T>(0, 60, 0, 0, test::limited_range) {}
+};
+
+template <class T> struct assign_test4 : assign_values<T>
+{
+ assign_test4() : assign_values<T>(10, 10, 1, 2) {}
+};
+
+template <class T> struct assign_test4a : assign_values<T>
+{
+ assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
+};
+
+template <class T> struct assign_test4b : assign_values<T>
+{
+ assign_test4b() : assign_values<T>(10, 100, 1, 2, test::limited_range) {}
+};
+
+template <class T> struct assign_test5 : assign_values<T>
+{
+ assign_test5()
+ : assign_values<T>(5, 60, 0, 0, test::default_generator, 1.0f, 0.1f)
+ {
+ }
+};
+
+template <class T> struct equivalent_test1 : assign_base<T>
+{
+ equivalent_test1() : assign_base<T>(0, 0)
+ {
+ test::random_values<T> x_values2(10);
+ this->x_values.insert(x_values2.begin(), x_values2.end());
+ this->x_values.insert(x_values2.begin(), x_values2.end());
+ test::random_values<T> y_values2(10);
+ this->y_values.insert(y_values2.begin(), y_values2.end());
+ this->y_values.insert(y_values2.begin(), y_values2.end());
+ this->x.insert(this->x_values.begin(), this->x_values.end());
+ this->y.insert(this->y_values.begin(), this->y_values.end());
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS_REPEAT(5,
+ (self_assign_test1)(self_assign_test2)
+ (assign_test1)(assign_test2)(assign_test2a)
+ (assign_test3)(assign_test3a)
+ (assign_test4)(assign_test4a)(assign_test4b)
+ (assign_test5)
+ (equivalent_test1),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/constructor_exception_tests.cpp b/src/boost/libs/unordered/test/exception/constructor_exception_tests.cpp
new file mode 100644
index 000000000..3dfebceff
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/constructor_exception_tests.cpp
@@ -0,0 +1,212 @@
+
+// Copyright 2006-2009 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 "./containers.hpp"
+
+#include "../helpers/input_iterator.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+template <typename T> inline void avoid_unused_warning(T const&) {}
+
+test::seed_t initialize_seed(91274);
+
+struct objects
+{
+ test::exception::object obj;
+ test::exception::hash hash;
+ test::exception::equal_to equal_to;
+ test::exception::allocator<test::exception::object> allocator;
+};
+
+template <class T> struct construct_test1 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x;
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test2 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(300);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test3 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(0, hash);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test4 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(0, hash, equal_to);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test5 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(50, hash, equal_to, allocator);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct construct_test6 : public objects, test::exception_base
+{
+ void run() const
+ {
+ T x(allocator);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct range : public test::exception_base
+{
+ test::random_values<T> values;
+
+ range() : values(5, test::limited_range) {}
+ range(unsigned int count) : values(count, test::limited_range) {}
+};
+
+template <class T> struct range_construct_test1 : public range<T>, objects
+{
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end());
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct range_construct_test2 : public range<T>, objects
+{
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end(), 0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct range_construct_test3 : public range<T>, objects
+{
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end(), 0, hash);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct range_construct_test4 : public range<T>, objects
+{
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+// Need to run at least one test with a fairly large number
+// of objects in case it triggers a rehash.
+template <class T> struct range_construct_test5 : public range<T>, objects
+{
+ range_construct_test5() : range<T>(60) {}
+
+ void run() const
+ {
+ T x(this->values.begin(), this->values.end(), 0, hash, equal_to, allocator);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct input_range_construct_test : public range<T>, objects
+{
+ input_range_construct_test() : range<T>(60) {}
+
+ void run() const
+ {
+ 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);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct copy_range_construct_test : public range<T>, objects
+{
+ copy_range_construct_test() : range<T>(60) {}
+
+ void run() const
+ {
+ T x(test::copy_iterator(this->values.begin()),
+ test::copy_iterator(this->values.end()), 0, hash, equal_to, allocator);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (construct_test1)(construct_test2)(construct_test3)(construct_test4)
+ (construct_test5)(construct_test6)(range_construct_test1)
+ (range_construct_test2)(range_construct_test3)(range_construct_test4)
+ (range_construct_test5)(input_range_construct_test)
+ (copy_range_construct_test),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/containers.hpp b/src/boost/libs/unordered/test/exception/containers.hpp
new file mode 100644
index 000000000..c3b34be24
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/containers.hpp
@@ -0,0 +1,44 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../objects/exception.hpp"
+
+typedef boost::unordered_set<test::exception::object, test::exception::hash,
+ test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >
+ test_set;
+typedef boost::unordered_multiset<test::exception::object,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >
+ test_multiset;
+typedef boost::unordered_map<test::exception::object, test::exception::object,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >
+ test_map;
+typedef boost::unordered_multimap<test::exception::object,
+ test::exception::object, test::exception::hash, test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >
+ test_multimap;
+typedef boost::unordered_set<
+ std::pair<test::exception::object, test::exception::object>,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >
+ test_pair_set;
+typedef boost::unordered_multiset<
+ std::pair<test::exception::object, test::exception::object>,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >
+ test_pair_multiset;
+
+#define CONTAINER_SEQ (test_set)(test_multiset)(test_map)(test_multimap)
+#define CONTAINER_PAIR_SEQ \
+ (test_pair_set)(test_pair_multiset)(test_map)(test_multimap)
diff --git a/src/boost/libs/unordered/test/exception/copy_exception_tests.cpp b/src/boost/libs/unordered/test/exception/copy_exception_tests.cpp
new file mode 100644
index 000000000..6149235aa
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/copy_exception_tests.cpp
@@ -0,0 +1,110 @@
+
+// Copyright 2006-2009 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 "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+template <typename T> inline void avoid_unused_warning(T const&) {}
+
+test::seed_t initialize_seed(73041);
+
+template <class T> struct copy_test1 : public test::exception_base
+{
+ T x;
+
+ void run() const
+ {
+ T y(x);
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(y.empty());
+ test::check_equivalent_keys(y);
+ }
+};
+
+template <class T> struct copy_test2 : public test::exception_base
+{
+ test::random_values<T> values;
+ T x;
+
+ copy_test2() : values(5, test::limited_range), x(values.begin(), values.end())
+ {
+ }
+
+ void run() const
+ {
+ T y(x);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(y, this->values);
+ test::check_equivalent_keys(y);
+ }
+};
+
+template <class T> struct copy_test3 : public test::exception_base
+{
+ test::random_values<T> values;
+ T x;
+
+ copy_test3() : values(100), x(values.begin(), values.end()) {}
+
+ void run() const
+ {
+ T y(x);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(y, this->values);
+ test::check_equivalent_keys(y);
+ }
+};
+
+template <class T> struct copy_test3a : public test::exception_base
+{
+ test::random_values<T> values;
+ T x;
+
+ copy_test3a()
+ : values(100, test::limited_range), x(values.begin(), values.end())
+ {
+ }
+
+ void run() const
+ {
+ T y(x);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(y, this->values);
+ test::check_equivalent_keys(y);
+ }
+};
+
+template <class T> struct copy_with_allocator_test : public test::exception_base
+{
+ test::random_values<T> values;
+ T x;
+ test::exception::allocator<test::exception::object> allocator;
+
+ copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {}
+
+ void run() const
+ {
+ T y(x, allocator);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(y, this->values);
+ test::check_equivalent_keys(y);
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (copy_test1)(copy_test2)(copy_test3)(copy_test3a)(copy_with_allocator_test),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/erase_exception_tests.cpp b/src/boost/libs/unordered/test/exception/erase_exception_tests.cpp
new file mode 100644
index 000000000..0f2c1eb61
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/erase_exception_tests.cpp
@@ -0,0 +1,55 @@
+
+// Copyright 2006-2009 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 "./containers.hpp"
+
+#include "../helpers/helpers.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+
+test::seed_t initialize_seed(835193);
+
+template <class T> struct erase_test_base : public test::exception_base
+{
+ test::random_values<T> values;
+ erase_test_base(unsigned int count = 5) : values(count, test::limited_range)
+ {
+ }
+
+ typedef T data_type;
+
+ data_type init() const { return T(values.begin(), values.end()); }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
+ {
+ std::string scope(test::scope);
+
+ BOOST_TEST(scope.find("hash::") != std::string::npos ||
+ scope.find("equal_to::") != std::string::npos ||
+ scope == "operator==(object, object)");
+
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct erase_by_key_test1 : public erase_test_base<T>
+{
+ void run(T& x) const
+ {
+ typedef typename test::random_values<T>::const_iterator iterator;
+
+ for (iterator it = this->values.begin(), end = this->values.end();
+ it != end; ++it) {
+ x.erase(test::get_key<T>(*it));
+ }
+
+ DISABLE_EXCEPTIONS;
+ BOOST_TEST(x.empty());
+ test::check_equivalent_keys(x);
+ }
+};
+
+EXCEPTION_TESTS((erase_by_key_test1), CONTAINER_SEQ)
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/insert_exception_tests.cpp b/src/boost/libs/unordered/test/exception/insert_exception_tests.cpp
new file mode 100644
index 000000000..79074c5ee
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/insert_exception_tests.cpp
@@ -0,0 +1,416 @@
+
+// Copyright 2006-2009 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 "./containers.hpp"
+
+#include "../helpers/helpers.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/strong.hpp"
+#include "../helpers/tracker.hpp"
+#include <cmath>
+#include <string>
+
+test::seed_t initialize_seed(747373);
+
+// Fill in a container so that it's about to rehash
+template <typename T> void rehash_prep(T& x)
+{
+ using namespace std;
+ typedef typename T::size_type size_type;
+
+ x.max_load_factor(0.25);
+ size_type bucket_count = x.bucket_count();
+ size_type initial_elements = static_cast<size_type>(
+ ceil((double)bucket_count * (double)x.max_load_factor()) - 1);
+ test::random_values<T> v(initial_elements);
+ x.insert(v.begin(), v.end());
+ BOOST_TEST(bucket_count == x.bucket_count());
+}
+
+// Overload to generate inserters that need type information.
+
+template <typename Inserter, typename T>
+Inserter generate(Inserter inserter, T&)
+{
+ return inserter;
+}
+
+// Get the iterator returned from an insert/emplace.
+
+template <typename T> T get_iterator(T const& x) { return x; }
+
+template <typename T> T get_iterator(std::pair<T, bool> const& x)
+{
+ return x.first;
+}
+
+// Generic insert exception test for typical single element inserts..
+
+template <typename T, typename Inserter, typename Values>
+void insert_exception_test_impl(T x, Inserter insert, Values const& v)
+{
+ test::strong<T> strong;
+
+ test::ordered<T> tracker;
+ tracker.insert(x.begin(), x.end());
+
+ try {
+ ENABLE_EXCEPTIONS;
+
+ for (typename Values::const_iterator it = v.begin(); it != v.end(); ++it) {
+ strong.store(x, test::detail::tracker.count_allocations);
+ insert(x, it);
+ }
+ } catch (...) {
+ test::check_equivalent_keys(x);
+ insert.exception_check(x, strong);
+ throw;
+ }
+
+ test::check_equivalent_keys(x);
+ insert.track(tracker, v.begin(), v.end());
+ tracker.compare(x);
+}
+
+// Simple insert exception test
+
+template <typename T, typename Inserter>
+void insert_exception_test(T*, Inserter insert, test::random_generator gen)
+{
+ for (int i = 0; i < 5; ++i) {
+ test::random_values<T> v(10, gen);
+ T x;
+
+ EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v));
+ }
+}
+
+// Insert into a container which is about to hit its max load, so that it
+// rehashes.
+
+template <typename T, typename Inserter>
+void insert_rehash_exception_test(
+ T*, Inserter insert, test::random_generator gen)
+{
+ for (int i = 0; i < 5; ++i) {
+ T x;
+ rehash_prep(x);
+
+ test::random_values<T> v2(5, gen);
+ EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v2));
+ }
+}
+
+// Various methods for inserting a single element
+
+struct inserter_base
+{
+ template <typename T> void exception_check(T& x, test::strong<T>& strong)
+ {
+ std::string scope(test::scope);
+
+ if (scope.find("hash::operator()") == std::string::npos)
+ strong.test(x, test::detail::tracker.count_allocations);
+ }
+
+ template <typename T, typename Iterator>
+ void track(T& tracker, Iterator begin, Iterator end)
+ {
+ tracker.insert(begin, end);
+ }
+};
+
+struct insert_lvalue_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert(*it);
+ }
+} insert_lvalue;
+
+struct insert_lvalue_begin_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert(x.begin(), *it);
+ }
+} insert_lvalue_begin;
+
+struct insert_lvalue_end_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert(x.end(), *it);
+ }
+} insert_lvalue_end;
+
+template <typename T> struct insert_lvalue_pos_type_impl : inserter_base
+{
+ typename T::iterator pos;
+
+ insert_lvalue_pos_type_impl(T& x) : pos(x.begin()) {}
+
+ template <typename Iterator> void operator()(T& x, Iterator it)
+ {
+ pos = get_iterator(x.insert(pos, *it));
+ }
+};
+
+struct insert_lvalue_pos_type
+{
+ template <typename T>
+ friend insert_lvalue_pos_type_impl<T> generate(insert_lvalue_pos_type, T& x)
+ {
+ return insert_lvalue_pos_type_impl<T>(x);
+ }
+} insert_lvalue_pos;
+
+struct insert_single_item_range_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert(it, test::next(it));
+ }
+} insert_single_item_range;
+
+struct emplace_lvalue_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace(*it);
+ }
+} emplace_lvalue;
+
+struct emplace_lvalue_begin_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace_hint(x.begin(), *it);
+ }
+} emplace_lvalue_begin;
+
+struct emplace_lvalue_end_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace_hint(x.end(), *it);
+ }
+} emplace_lvalue_end;
+
+template <typename T> struct emplace_lvalue_pos_type_impl : inserter_base
+{
+ typename T::iterator pos;
+
+ emplace_lvalue_pos_type_impl(T& x) : pos(x.begin()) {}
+
+ template <typename Iterator> void operator()(T& x, Iterator it)
+ {
+ pos = get_iterator(x.emplace_hint(pos, *it));
+ }
+};
+
+struct emplace_lvalue_pos_type
+{
+ template <typename T>
+ friend emplace_lvalue_pos_type_impl<T> generate(emplace_lvalue_pos_type, T& x)
+ {
+ return emplace_lvalue_pos_type_impl<T>(x);
+ }
+} emplace_lvalue_pos;
+
+// Run the exception tests in various combinations.
+
+test_set* test_set_;
+test_multiset* test_multiset_;
+test_map* test_map_;
+test_multimap* test_multimap_;
+
+using test::default_generator;
+using test::limited_range;
+using test::generate_collisions;
+
+// clang-format off
+UNORDERED_TEST(insert_exception_test,
+ ((test_set_)(test_multiset_)(test_map_)(test_multimap_))
+ ((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
+ (insert_lvalue_pos)(insert_single_item_range)
+ (emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
+ (emplace_lvalue_pos)
+ )
+ ((default_generator)(limited_range)(generate_collisions))
+)
+
+UNORDERED_TEST(insert_rehash_exception_test,
+ ((test_set_)(test_multiset_)(test_map_)(test_multimap_))
+ ((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
+ (insert_lvalue_pos)(insert_single_item_range)
+ (emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
+ (emplace_lvalue_pos)
+ )
+ ((default_generator)(limited_range)(generate_collisions))
+)
+// clang-format on
+
+// Repeat insert tests with pairs
+
+struct pair_emplace_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace(boost::unordered::piecewise_construct,
+ boost::make_tuple(it->first), boost::make_tuple(it->second));
+ }
+} pair_emplace;
+
+struct pair_emplace2_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.emplace_hint(x.begin(), boost::unordered::piecewise_construct,
+ boost::make_tuple(it->first),
+ boost::make_tuple(it->second.tag1_, it->second.tag2_));
+ }
+} pair_emplace2;
+
+test_pair_set* test_pair_set_;
+test_pair_multiset* test_pair_multiset_;
+
+// clang-format off
+UNORDERED_TEST(insert_exception_test,
+ ((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
+ ((pair_emplace)(pair_emplace2))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+UNORDERED_TEST(insert_rehash_exception_test,
+ ((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
+ ((pair_emplace)(pair_emplace2))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+// clang-format on
+
+// Test inserting using operator[]
+
+struct try_emplace_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.try_emplace(it->first, it->second);
+ }
+} try_emplace;
+
+struct try_emplace2_type : inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.try_emplace(it->first, it->second.tag1_, it->second.tag2_);
+ }
+} try_emplace2;
+
+struct map_inserter_base
+{
+ template <typename T> void exception_check(T& x, test::strong<T>& strong)
+ {
+ std::string scope(test::scope);
+
+ if (scope.find("hash::operator()") == std::string::npos &&
+ scope.find("::operator=") == std::string::npos)
+ strong.test(x, test::detail::tracker.count_allocations);
+ }
+
+ template <typename T, typename Iterator>
+ void track(T& tracker, Iterator begin, Iterator end)
+ {
+ for (; begin != end; ++begin) {
+ tracker[begin->first] = begin->second;
+ }
+ }
+};
+
+struct map_insert_operator_type : map_inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x[it->first] = it->second;
+ }
+} map_insert_operator;
+
+struct map_insert_or_assign_type : map_inserter_base
+{
+ template <typename T, typename Iterator> void operator()(T& x, Iterator it)
+ {
+ x.insert_or_assign(it->first, it->second);
+ }
+} map_insert_or_assign;
+
+// clang-format off
+UNORDERED_TEST(insert_exception_test,
+ ((test_map_))
+ ((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+UNORDERED_TEST(insert_rehash_exception_test,
+ ((test_map_))
+ ((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+// clang-format on
+
+// Range insert tests
+
+template <typename T, typename Values>
+void insert_range_exception_test_impl(T x, Values const& v)
+{
+ test::ordered<T> tracker;
+ tracker.insert(x.begin(), x.end());
+
+ try {
+ ENABLE_EXCEPTIONS;
+ x.insert(v.begin(), v.end());
+ } catch (...) {
+ test::check_equivalent_keys(x);
+ throw;
+ }
+
+ test::check_equivalent_keys(x);
+ tracker.insert(v.begin(), v.end());
+ tracker.compare(x);
+}
+
+template <typename T>
+void insert_range_exception_test(T*, test::random_generator gen)
+{
+ for (int i = 0; i < 5; ++i) {
+ test::random_values<T> v(10, gen);
+ T x;
+
+ EXCEPTION_LOOP(insert_range_exception_test_impl(x, v));
+ }
+}
+
+template <typename T>
+void insert_range_rehash_exception_test(T*, test::random_generator gen)
+{
+ for (int i = 0; i < 5; ++i) {
+ T x;
+ rehash_prep(x);
+
+ test::random_values<T> v2(5, gen);
+ EXCEPTION_LOOP(insert_range_exception_test_impl(x, v2));
+ }
+}
+
+// clang-format off
+UNORDERED_TEST(insert_range_exception_test,
+ ((test_set_)(test_multiset_)(test_map_)(test_multimap_))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+
+UNORDERED_TEST(insert_range_rehash_exception_test,
+ ((test_set_)(test_multiset_)(test_map_)(test_multimap_))
+ ((default_generator)(limited_range)(generate_collisions))
+)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/merge_exception_tests.cpp b/src/boost/libs/unordered/test/exception/merge_exception_tests.cpp
new file mode 100644
index 000000000..2cf7faf44
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/merge_exception_tests.cpp
@@ -0,0 +1,108 @@
+
+// Copyright 2017-2018 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/exception_test.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/metafunctions.hpp"
+#include "../helpers/random_values.hpp"
+#include "./containers.hpp"
+
+template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y)
+{
+ std::size_t size = x.size() + y.size();
+
+ try {
+ ENABLE_EXCEPTIONS;
+ x.merge(y);
+ } catch (...) {
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ throw;
+ }
+
+ // Not a full check, just want to make sure the merge completed.
+ BOOST_TEST(size == x.size() + y.size());
+ if (y.size()) {
+ BOOST_TEST(test::has_unique_keys<T1>::value);
+ for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
+ BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
+ }
+ }
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+}
+
+template <typename T1, typename T2>
+void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12,
+ test::random_generator gen1, test::random_generator gen2)
+{
+ std::size_t count1 = count12 / 256;
+ std::size_t count2 = count12 % 256;
+ int tag1 = tag12 / 256;
+ int tag2 = tag12 % 256;
+ test::random_values<T1> v1(count1, gen1);
+ test::random_values<T2> v2(count2, gen2);
+ T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1),
+ test::exception::equal_to(tag1));
+ T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2),
+ test::exception::equal_to(tag2));
+
+ EXCEPTION_LOOP(merge_exception_test(x, y))
+}
+
+boost::unordered_set<test::exception::object, test::exception::hash,
+ test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >* test_set_;
+boost::unordered_multiset<test::exception::object, test::exception::hash,
+ test::exception::equal_to,
+ test::exception::allocator<test::exception::object> >* test_multiset_;
+boost::unordered_map<test::exception::object, test::exception::object,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >* test_map_;
+boost::unordered_multimap<test::exception::object, test::exception::object,
+ test::exception::hash, test::exception::equal_to,
+ test::exception::allocator2<test::exception::object> >* test_multimap_;
+
+using test::default_generator;
+using test::generate_collisions;
+using test::limited_range;
+
+// clang-format off
+UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
+ ((test_set_)(test_multiset_))
+ ((test_set_)(test_multiset_))
+ ((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
+ ((0x0000)(0x0001)(0x0102))
+ ((default_generator)(limited_range))
+ ((default_generator)(limited_range))
+)
+UNORDERED_MULTI_TEST(map_merge, merge_exception_test,
+ ((test_map_)(test_multimap_))
+ ((test_map_)(test_multimap_))
+ ((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
+ ((0x0101)(0x0200)(0x0201))
+ ((default_generator)(limited_range))
+ ((default_generator)(limited_range))
+)
+// Run fewer generate_collisions tests, as they're slow.
+UNORDERED_MULTI_TEST(set_merge_collisions, merge_exception_test,
+ ((test_set_)(test_multiset_))
+ ((test_set_)(test_multiset_))
+ ((0x0a0a))
+ ((0x0202)(0x0100)(0x0201))
+ ((generate_collisions))
+ ((generate_collisions))
+)
+UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
+ ((test_map_)(test_multimap_))
+ ((test_map_)(test_multimap_))
+ ((0x0a0a))
+ ((0x0000)(0x0002)(0x0102))
+ ((generate_collisions))
+ ((generate_collisions))
+)
+// clang-format on
+
+RUN_TESTS_QUIET()
diff --git a/src/boost/libs/unordered/test/exception/move_assign_exception_tests.cpp b/src/boost/libs/unordered/test/exception/move_assign_exception_tests.cpp
new file mode 100644
index 000000000..6beb68202
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/move_assign_exception_tests.cpp
@@ -0,0 +1,132 @@
+
+// Copyright 2006-2009 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 "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning( \
+ disable : 4512) // move_assignment operator could not be generated
+#endif
+
+test::seed_t initialize_seed(12847);
+
+template <class T> struct move_assign_base : public test::exception_base
+{
+ test::random_values<T> x_values, y_values;
+ T x, y;
+
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::allocator_type allocator_type;
+
+ move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
+ : x_values(), y_values(),
+ x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
+ y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
+ {
+ x.max_load_factor(mlf1);
+ y.max_load_factor(mlf2);
+ }
+
+ typedef T data_type;
+ T init() const { return T(x); }
+ void run(T& x1) const
+ {
+ test::exceptions_enable disable_exceptions(false);
+ T y1 = y;
+ disable_exceptions.release();
+ x1 = boost::move(y1);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x1, y_values);
+ test::check_equivalent_keys(x1);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
+ {
+ test::check_equivalent_keys(x1);
+
+ // If the container is empty at the point of the exception, the
+ // internal structure is hidden, this exposes it, at the cost of
+ // messing up the data.
+ if (x_values.size()) {
+ T& x2 = const_cast<T&>(x1);
+ x2.emplace(*x_values.begin());
+ test::check_equivalent_keys(x2);
+ }
+ }
+};
+
+template <class T> struct move_assign_values : move_assign_base<T>
+{
+ move_assign_values(unsigned int count1, unsigned int count2, int tag1,
+ int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
+ : move_assign_base<T>(tag1, tag2, mlf1, mlf2)
+ {
+ this->x_values.fill(count1, test::limited_range);
+ this->y_values.fill(count2, test::limited_range);
+ this->x.insert(this->x_values.begin(), this->x_values.end());
+ this->y.insert(this->y_values.begin(), this->y_values.end());
+ }
+};
+
+template <class T> struct move_assign_test1 : move_assign_values<T>
+{
+ move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
+};
+
+template <class T> struct move_assign_test2 : move_assign_values<T>
+{
+ move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
+};
+
+template <class T> struct move_assign_test3 : move_assign_values<T>
+{
+ move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
+};
+
+template <class T> struct move_assign_test4 : move_assign_values<T>
+{
+ move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
+};
+
+template <class T> struct move_assign_test4a : move_assign_values<T>
+{
+ move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
+};
+
+template <class T> struct move_assign_test5 : move_assign_values<T>
+{
+ move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
+};
+
+template <class T> struct equivalent_test1 : move_assign_base<T>
+{
+ equivalent_test1() : move_assign_base<T>(0, 0)
+ {
+ test::random_values<T> x_values2(10, test::limited_range);
+ this->x_values.insert(x_values2.begin(), x_values2.end());
+ this->x_values.insert(x_values2.begin(), x_values2.end());
+ test::random_values<T> y_values2(10, test::limited_range);
+ this->y_values.insert(y_values2.begin(), y_values2.end());
+ this->y_values.insert(y_values2.begin(), y_values2.end());
+ this->x.insert(this->x_values.begin(), this->x_values.end());
+ this->y.insert(this->y_values.begin(), this->y_values.end());
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (move_assign_test1)(move_assign_test2)(move_assign_test3)
+ (move_assign_test4)(move_assign_test4a)(move_assign_test5)
+ (equivalent_test1),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/rehash_exception_tests.cpp b/src/boost/libs/unordered/test/exception/rehash_exception_tests.cpp
new file mode 100644
index 000000000..a927d1368
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/rehash_exception_tests.cpp
@@ -0,0 +1,133 @@
+
+// Copyright 2006-2009 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 "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/strong.hpp"
+#include "../helpers/tracker.hpp"
+#include <string>
+
+test::seed_t initialize_seed(3298597);
+
+template <class T> struct rehash_test_base : public test::exception_base
+{
+ test::random_values<T> values;
+ unsigned int n;
+ rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
+ : values(count, test::limited_range), n(n_)
+ {
+ }
+
+ typedef T data_type;
+ typedef test::strong<T> strong_type;
+
+ data_type init() const
+ {
+ T x(values.begin(), values.end(), n);
+ return x;
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(
+ T const& x, strong_type const& strong) const
+ {
+ std::string scope(test::scope);
+
+ if (scope.find("hash::operator()") == std::string::npos &&
+ scope.find("equal_to::operator()") == std::string::npos &&
+ scope != "operator==(object, object)")
+ strong.test(x);
+
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test0 : rehash_test_base<T>
+{
+ rehash_test0() : rehash_test_base<T>(0) {}
+ void run(T& x) const
+ {
+ x.rehash(0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test1 : rehash_test_base<T>
+{
+ rehash_test1() : rehash_test_base<T>(0) {}
+ void run(T& x) const
+ {
+ x.rehash(200);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test2 : rehash_test_base<T>
+{
+ rehash_test2() : rehash_test_base<T>(0, 200) {}
+ void run(T& x) const
+ {
+ x.rehash(0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test3 : rehash_test_base<T>
+{
+ rehash_test3() : rehash_test_base<T>(10, 0) {}
+ void run(T& x) const
+ {
+ x.rehash(200);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test4 : rehash_test_base<T>
+{
+ rehash_test4() : rehash_test_base<T>(10, 200) {}
+ void run(T& x) const
+ {
+ x.rehash(0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct rehash_test5 : rehash_test_base<T>
+{
+ rehash_test5() : rehash_test_base<T>(200, 10) {}
+ void run(T& x) const
+ {
+ x.rehash(0);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4)
+ (rehash_test5),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/exception/swap_exception_tests.cpp b/src/boost/libs/unordered/test/exception/swap_exception_tests.cpp
new file mode 100644
index 000000000..1569e814c
--- /dev/null
+++ b/src/boost/libs/unordered/test/exception/swap_exception_tests.cpp
@@ -0,0 +1,145 @@
+
+// Copyright 2006-2009 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 "./containers.hpp"
+
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#endif
+
+test::seed_t initialize_seed(9387);
+
+template <class T> struct self_swap_base : public test::exception_base
+{
+ test::random_values<T> values;
+ self_swap_base(std::size_t count = 0) : values(count, test::limited_range) {}
+
+ typedef T data_type;
+ T init() const { return T(values.begin(), values.end()); }
+
+ void run(T& x) const
+ {
+ x.swap(x);
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(x, this->values);
+ test::check_equivalent_keys(x);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
+ {
+ std::string scope(test::scope);
+
+ // TODO: In C++11 exceptions are only allowed in the swap function.
+ BOOST_TEST(scope == "hash::hash(hash)" ||
+ scope == "hash::operator=(hash)" ||
+ scope == "equal_to::equal_to(equal_to)" ||
+ scope == "equal_to::operator=(equal_to)");
+
+ test::check_equivalent_keys(x);
+ }
+};
+
+template <class T> struct self_swap_test1 : self_swap_base<T>
+{
+};
+
+template <class T> struct self_swap_test2 : self_swap_base<T>
+{
+ self_swap_test2() : self_swap_base<T>(100) {}
+};
+
+template <class T> struct swap_base : public test::exception_base
+{
+ const test::random_values<T> x_values, y_values;
+ const T initial_x, initial_y;
+
+ typedef typename T::hasher hasher;
+ typedef typename T::key_equal key_equal;
+ typedef typename T::allocator_type allocator_type;
+
+ swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
+ : x_values(count1, test::limited_range),
+ y_values(count2, test::limited_range),
+ initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
+ key_equal(tag1), allocator_type(tag1)),
+ initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
+ key_equal(tag2),
+ allocator_type(T::allocator_type::propagate_on_container_swap::value
+ ? tag2
+ : tag1))
+ {
+ }
+
+ struct data_type
+ {
+ data_type(T const& x_, T const& y_) : x(x_), y(y_) {}
+
+ T x, y;
+ };
+
+ data_type init() const { return data_type(initial_x, initial_y); }
+
+ void run(data_type& d) const
+ {
+ try {
+ d.x.swap(d.y);
+ } catch (std::runtime_error&) {
+ }
+
+ DISABLE_EXCEPTIONS;
+ test::check_container(d.x, this->y_values);
+ test::check_equivalent_keys(d.x);
+ test::check_container(d.y, this->x_values);
+ test::check_equivalent_keys(d.y);
+ }
+
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const
+ {
+ std::string scope(test::scope);
+
+ // TODO: In C++11 exceptions are only allowed in the swap function.
+ BOOST_TEST(scope == "hash::hash(hash)" ||
+ scope == "hash::operator=(hash)" ||
+ scope == "equal_to::equal_to(equal_to)" ||
+ scope == "equal_to::operator=(equal_to)");
+
+ test::check_equivalent_keys(d.x);
+ test::check_equivalent_keys(d.y);
+ }
+};
+
+template <class T> struct swap_test1 : swap_base<T>
+{
+ swap_test1() : swap_base<T>(0, 0, 0, 0) {}
+};
+
+template <class T> struct swap_test2 : swap_base<T>
+{
+ swap_test2() : swap_base<T>(60, 0, 0, 0) {}
+};
+
+template <class T> struct swap_test3 : swap_base<T>
+{
+ swap_test3() : swap_base<T>(0, 60, 0, 0) {}
+};
+
+template <class T> struct swap_test4 : swap_base<T>
+{
+ swap_test4() : swap_base<T>(10, 10, 1, 2) {}
+};
+
+// clang-format off
+EXCEPTION_TESTS(
+ (self_swap_test1)(self_swap_test2)
+ (swap_test1)(swap_test2)(swap_test3)(swap_test4),
+ CONTAINER_SEQ)
+// clang-format on
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/helpers/check_return_type.hpp b/src/boost/libs/unordered/test/helpers/check_return_type.hpp
new file mode 100644
index 000000000..1c70a8c7f
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/check_return_type.hpp
@@ -0,0 +1,33 @@
+
+// Copyright 2005-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace test {
+ template <class T1> struct check_return_type
+ {
+ template <class T2> static void equals(T2)
+ {
+ BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
+ }
+
+ template <class T2> static void equals_ref(T2&)
+ {
+ BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
+ }
+
+ template <class T2> static void convertible(T2)
+ {
+ BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/count.hpp b/src/boost/libs/unordered/test/helpers/count.hpp
new file mode 100644
index 000000000..90372dca3
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/count.hpp
@@ -0,0 +1,89 @@
+
+// Copyright 2008-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD)
+#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
+
+#include <boost/core/lightweight_test.hpp>
+
+namespace test {
+ struct object_count
+ {
+ int instances;
+ int constructions;
+
+ object_count() : instances(0), constructions(0) {}
+ void reset() { *this = object_count(); }
+
+ void construct()
+ {
+ ++instances;
+ ++constructions;
+ }
+
+ void destruct()
+ {
+ if (instances == 0) {
+ BOOST_ERROR("Unbalanced constructions.");
+ } else {
+ --instances;
+ }
+ }
+
+ bool operator==(object_count const& x) const
+ {
+ return instances == x.instances && constructions == x.constructions;
+ }
+
+ bool operator!=(object_count const& x) const { return !(*this == x); }
+
+ friend std::ostream& operator<<(std::ostream& out, object_count const& c)
+ {
+ out << "[instances: " << c.instances
+ << ", constructions: " << c.constructions << "]";
+ return out;
+ }
+ };
+
+ // This won't be a problem as I'm only using a single compile unit
+ // in each test (this is actually require by the minimal test
+ // framework).
+ //
+ // boostinspect:nounnamed
+ namespace {
+ object_count global_object_count;
+ }
+
+ struct counted_object
+ {
+ counted_object() { global_object_count.construct(); }
+ counted_object(counted_object const&) { global_object_count.construct(); }
+ ~counted_object() { global_object_count.destruct(); }
+ };
+
+ struct check_instances
+ {
+ int instances_;
+ int constructions_;
+
+ 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_;
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/equivalent.hpp b/src/boost/libs/unordered/test/helpers/equivalent.hpp
new file mode 100644
index 000000000..bd27d8df2
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/equivalent.hpp
@@ -0,0 +1,96 @@
+
+// Copyright 2005-2009 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)
+
+#if !defined(BOOST_UNORDERED_TESTS_EQUIVALENT_HEADER)
+#define BOOST_UNORDERED_TESTS_EQUIVALENT_HEADER
+
+#include "./fwd.hpp"
+#include "./list.hpp"
+#include "./metafunctions.hpp"
+#include <algorithm>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+
+namespace test {
+ template <class T1, class T2>
+ bool equivalent_impl(T1 const& x, T2 const& y, base_type)
+ {
+ return x == y;
+ }
+
+ template <class T>
+ bool equivalent_impl(
+ boost::hash<T> const&, boost::hash<T> const&, derived_type)
+ {
+ return true;
+ }
+
+ template <class T>
+ bool equivalent_impl(
+ std::equal_to<T> const&, std::equal_to<T> const&, derived_type)
+ {
+ return true;
+ }
+
+ template <class T1, class T2, class T3, class T4>
+ bool equivalent_impl(
+ std::pair<T1, T2> const& x1, std::pair<T3, T4> const& x2, derived_type)
+ {
+ return equivalent_impl(x1.first, x2.first, derived) &&
+ equivalent_impl(x1.second, x2.second, derived);
+ }
+
+ struct equivalent_type
+ {
+ equivalent_type() {}
+
+ template <class T1, class T2>
+ bool operator()(T1 const& x, T2 const& y) const
+ {
+ return equivalent_impl(x, y, derived);
+ }
+ };
+
+ const equivalent_type equivalent;
+
+ template <class Container> class unordered_equivalence_tester
+ {
+ typename Container::size_type size_;
+ typename Container::hasher hasher_;
+ typename Container::key_equal key_equal_;
+ float max_load_factor_;
+
+ typedef test::list<typename Container::value_type> value_list;
+ value_list values_;
+
+ public:
+ unordered_equivalence_tester(Container const& x)
+ : size_(x.size()), hasher_(x.hash_function()), key_equal_(x.key_eq()),
+ max_load_factor_(x.max_load_factor()), values_(x.begin(), x.end())
+ {
+ values_.sort();
+ }
+
+ bool operator()(Container const& x) const
+ {
+ if (!((size_ == x.size()) &&
+ (test::equivalent(hasher_, x.hash_function())) &&
+ (test::equivalent(key_equal_, x.key_eq())) &&
+ (max_load_factor_ == x.max_load_factor()) &&
+ (values_.size() == x.size())))
+ return false;
+
+ value_list copy(x.begin(), x.end());
+ copy.sort();
+ return values_ == copy;
+ }
+
+ private:
+ unordered_equivalence_tester();
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/exception_test.hpp b/src/boost/libs/unordered/test/helpers/exception_test.hpp
new file mode 100644
index 000000000..8984eee9b
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/exception_test.hpp
@@ -0,0 +1,348 @@
+
+// Copyright 2006-2009 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)
+
+#if !defined(BOOST_UNORDERED_EXCEPTION_TEST_HEADER)
+#define BOOST_UNORDERED_EXCEPTION_TEST_HEADER
+
+#include "./count.hpp"
+#include "./test.hpp"
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/seq/for_each_product.hpp>
+
+#define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
+ UNORDERED_AUTO_TEST (name) { \
+ test_func<type> fixture; \
+ ::test::lightweight::exception_safety( \
+ fixture, BOOST_STRINGIZE(test_func<type>)); \
+ }
+
+#define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
+ UNORDERED_AUTO_TEST (name) { \
+ for (unsigned i = 0; i < n; ++i) { \
+ test_func<type> fixture; \
+ ::test::lightweight::exception_safety( \
+ fixture, BOOST_STRINGIZE(test_func<type>)); \
+ } \
+ }
+
+#define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
+
+#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
+
+#define EXCEPTION_TESTS(test_seq, param_seq) \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((1))(param_seq))
+
+#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq))
+
+#define EXCEPTION_TESTS_OP(r, product) \
+ UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
+ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
+ BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))), \
+ BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product), \
+ BOOST_PP_SEQ_ELEM(2, product))
+
+#define UNORDERED_SCOPE(scope_name) \
+ for (::test::scope_guard unordered_test_guard(BOOST_STRINGIZE(scope_name)); \
+ !unordered_test_guard.dismissed(); unordered_test_guard.dismiss())
+
+#define UNORDERED_EPOINT(name) \
+ if (::test::exceptions_enabled) { \
+ UNORDERED_EPOINT_IMPL(name); \
+ }
+
+#define ENABLE_EXCEPTIONS \
+ ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true)
+
+#define DISABLE_EXCEPTIONS \
+ ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false)
+
+namespace test {
+ static char const* scope = "";
+ bool exceptions_enabled = false;
+
+ class scope_guard
+ {
+ scope_guard& operator=(scope_guard const&);
+ scope_guard(scope_guard const&);
+
+ char const* old_scope_;
+ char const* scope_;
+ bool dismissed_;
+
+ public:
+ scope_guard(char const* name)
+ : old_scope_(scope), scope_(name), dismissed_(false)
+ {
+ scope = scope_;
+ }
+
+ ~scope_guard()
+ {
+ if (dismissed_)
+ scope = old_scope_;
+ }
+
+ void dismiss() { dismissed_ = true; }
+
+ bool dismissed() const { return dismissed_; }
+ };
+
+ class exceptions_enable
+ {
+ exceptions_enable& operator=(exceptions_enable const&);
+ exceptions_enable(exceptions_enable const&);
+
+ bool old_value_;
+ bool released_;
+
+ public:
+ exceptions_enable(bool enable)
+ : old_value_(exceptions_enabled), released_(false)
+ {
+ exceptions_enabled = enable;
+ }
+
+ ~exceptions_enable()
+ {
+ if (!released_) {
+ exceptions_enabled = old_value_;
+ released_ = true;
+ }
+ }
+
+ void release()
+ {
+ if (!released_) {
+ exceptions_enabled = old_value_;
+ released_ = true;
+ }
+ }
+ };
+
+ struct exception_base
+ {
+ struct data_type
+ {
+ };
+ struct strong_type
+ {
+ template <class T> void store(T const&) {}
+ template <class T> void test(T const&) const {}
+ };
+ data_type init() const { return data_type(); }
+ void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
+ };
+
+ template <class T, class P1, class P2, class T2>
+ inline void call_ignore_extra_parameters(
+ void (T::*fn)() const, T2 const& obj, P1&, P2&)
+ {
+ (obj.*fn)();
+ }
+
+ template <class T, class P1, class P2, class T2>
+ inline void call_ignore_extra_parameters(
+ void (T::*fn)(P1&) const, T2 const& obj, P1& p1, P2&)
+ {
+ (obj.*fn)(p1);
+ }
+
+ template <class T, class P1, class P2, class T2>
+ inline void call_ignore_extra_parameters(
+ void (T::*fn)(P1&, P2&) const, T2 const& obj, P1& p1, P2& p2)
+ {
+ (obj.*fn)(p1, p2);
+ }
+
+ template <class T> T const& constant(T const& x) { return x; }
+
+ template <class Test> class test_runner
+ {
+ Test const& test_;
+ bool exception_in_check_;
+
+ test_runner(test_runner const&);
+ test_runner& operator=(test_runner const&);
+
+ public:
+ test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
+ void run()
+ {
+ DISABLE_EXCEPTIONS;
+ test::check_instances check;
+ test::scope = "";
+ typename Test::data_type x(test_.init());
+ typename Test::strong_type strong;
+ strong.store(x);
+ try {
+ ENABLE_EXCEPTIONS;
+ call_ignore_extra_parameters<Test, typename Test::data_type,
+ typename Test::strong_type>(&Test::run, test_, x, strong);
+ } catch (...) {
+ try {
+ DISABLE_EXCEPTIONS;
+ call_ignore_extra_parameters<Test, typename Test::data_type const,
+ typename Test::strong_type const>(
+ &Test::check, test_, constant(x), constant(strong));
+ } catch (...) {
+ exception_in_check_ = true;
+ }
+ throw;
+ }
+ }
+ void end()
+ {
+ if (exception_in_check_) {
+ BOOST_ERROR("Unexcpected exception in test_runner check call.");
+ }
+ }
+ };
+
+ // Quick exception testing based on lightweight test
+
+ namespace lightweight {
+ static int iteration;
+ static int count;
+
+ struct test_exception
+ {
+ char const* name;
+ test_exception(char const* n) : name(n) {}
+ };
+
+ struct test_failure
+ {
+ };
+
+ void epoint(char const* name)
+ {
+ ++count;
+ if (count == iteration) {
+ throw test_exception(name);
+ }
+ }
+
+ template <class Test>
+ void exception_safety(Test const& f, char const* /*name*/)
+ {
+ test_runner<Test> runner(f);
+
+ iteration = 0;
+ bool success = false;
+ unsigned int failure_count = 0;
+ char const* error_msg = 0;
+ do {
+ int error_count = boost::detail::test_errors();
+ ++iteration;
+ count = 0;
+
+ try {
+ runner.run();
+ success = true;
+ } catch (test_failure) {
+ error_msg = "test_failure caught.";
+ break;
+ } catch (test_exception e) {
+ if (error_count != boost::detail::test_errors()) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "Iteration: " << iteration
+ << " Error found for epoint: " << e.name << std::endl;
+ }
+ } catch (...) {
+ error_msg = "Unexpected exception.";
+ break;
+ }
+
+ if (error_count != boost::detail::test_errors()) {
+ ++failure_count;
+ }
+ } while (!success && failure_count < 5);
+
+ if (error_msg) {
+ BOOST_ERROR(error_msg);
+ }
+ runner.end();
+ }
+
+ //
+ // An alternative way to run exception tests.
+ // See merge_exception_tests.cpp for an example.
+
+ struct exception_looper
+ {
+ bool success;
+ unsigned int failure_count;
+ char const* error_msg;
+ int error_count;
+
+ exception_looper() : success(false), failure_count(0), error_msg(0) {}
+
+ void start() { iteration = 0; }
+
+ bool loop_condition() const
+ {
+ return !error_msg && !success && failure_count < 5;
+ }
+
+ void start_iteration()
+ {
+ error_count = boost::detail::test_errors();
+ ++iteration;
+ count = 0;
+ }
+
+ void successful_run() { success = true; }
+
+ void test_failure_caught(test_failure const&)
+ {
+ error_msg = "test_failure caught.";
+ }
+
+ void test_exception_caught(test_exception const& e)
+ {
+ if (error_count != boost::detail::test_errors()) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "Iteration: " << iteration
+ << " Error found for epoint: " << e.name << std::endl;
+ }
+ }
+
+ void unexpected_exception_caught()
+ {
+ error_msg = "Unexpected exception.";
+ }
+
+ void end()
+ {
+ if (error_msg) {
+ BOOST_ERROR(error_msg);
+ }
+ }
+ };
+
+#define EXCEPTION_LOOP(op) \
+ test::lightweight::exception_looper looper; \
+ looper.start(); \
+ while (looper.loop_condition()) { \
+ looper.start_iteration(); \
+ try { \
+ op; \
+ looper.successful_run(); \
+ } catch (test::lightweight::test_failure e) { \
+ looper.test_failure_caught(e); \
+ } catch (test::lightweight::test_exception e) { \
+ looper.test_exception_caught(e); \
+ } catch (...) { \
+ looper.unexpected_exception_caught(); \
+ } \
+ } \
+ looper.end();
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/fwd.hpp b/src/boost/libs/unordered/test/helpers/fwd.hpp
new file mode 100644
index 000000000..a5657e018
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/fwd.hpp
@@ -0,0 +1,32 @@
+
+// Copyright 2006-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_FWD_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_FWD_HEADER
+
+#include <string>
+
+namespace test {
+ typedef enum {
+ default_generator,
+ generate_collisions,
+ limited_range
+ } random_generator;
+
+ int generate(int const*, random_generator);
+ char generate(char const*, random_generator);
+ signed char generate(signed char const*, random_generator);
+ std::string generate(std::string const*, random_generator);
+ float generate(float const*, random_generator);
+
+ struct base_type
+ {
+ } base;
+ struct derived_type : base_type
+ {
+ } derived;
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/generators.hpp b/src/boost/libs/unordered/test/helpers/generators.hpp
new file mode 100644
index 000000000..c9ed42bdd
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/generators.hpp
@@ -0,0 +1,93 @@
+
+// Copyright 2005-2009 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)
+
+// This uses std::rand to generate random values for tests.
+// Which is not good as different platforms will be running different tests.
+// It would be much better to use Boost.Random, but it doesn't
+// support all the compilers that I want to test on.
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_GENERATORS_HEADER
+
+#include "./fwd.hpp"
+#include <boost/type_traits/add_const.hpp>
+#include <cstdlib>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+namespace test {
+ struct seed_t
+ {
+ seed_t(unsigned int x)
+ {
+ using namespace std;
+ srand(x);
+ }
+ };
+
+ std::size_t random_value(std::size_t max)
+ {
+ using namespace std;
+ return static_cast<std::size_t>(rand()) % max;
+ }
+
+ inline int generate(int const*, random_generator g)
+ {
+ using namespace std;
+ int value = rand();
+ if (g == limited_range) {
+ value = value % 100;
+ }
+ return value;
+ }
+
+ inline char generate(char const*, random_generator)
+ {
+ using namespace std;
+ return static_cast<char>((rand() >> 1) % (128 - 32) + 32);
+ }
+
+ inline signed char generate(signed char const*, random_generator)
+ {
+ using namespace std;
+ return static_cast<signed char>(rand());
+ }
+
+ inline std::string generate(std::string const*, random_generator g)
+ {
+ using namespace std;
+
+ char* char_ptr = 0;
+
+ std::string result;
+
+ if (g == limited_range) {
+ std::size_t length = test::random_value(2) + 2;
+
+ char const* strings[] = {"'vZh(3~ms", "%m", "_Y%U", "N'Y", "4,J_J"};
+ for (std::size_t i = 0; i < length; ++i) {
+ result += strings[random_value(sizeof(strings) / sizeof(strings[0]))];
+ }
+ } else {
+ std::size_t length = test::random_value(10) + 1;
+ for (std::size_t i = 0; i < length; ++i) {
+ result += generate(char_ptr, g);
+ }
+ }
+
+ return result;
+ }
+
+ float generate(float const*, random_generator g)
+ {
+ using namespace std;
+ int x = 0;
+ int value = generate(&x, g);
+ return (float)value / (float)RAND_MAX;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/helpers.hpp b/src/boost/libs/unordered/test/helpers/helpers.hpp
new file mode 100644
index 000000000..146dea4df
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/helpers.hpp
@@ -0,0 +1,56 @@
+
+// Copyright 2006-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_HEADER
+
+#include <iterator>
+
+namespace test {
+ template <class Container> struct get_key_impl
+ {
+ typedef typename Container::key_type key_type;
+
+ static key_type const& get_key(key_type const& x) { return x; }
+
+ template <class T>
+ static key_type const& get_key(std::pair<key_type, T> const& x, char = 0)
+ {
+ return x.first;
+ }
+
+ template <class T>
+ static key_type const& get_key(
+ std::pair<key_type const, T> const& x, unsigned char = 0)
+ {
+ return x.first;
+ }
+ };
+
+ template <class Container, class T>
+ inline typename Container::key_type const& get_key(T const& x)
+ {
+ return get_key_impl<Container>::get_key(x);
+ }
+
+ // test::next
+ //
+ // Increments an iterator by 1 or a given value.
+ // Like boost::next, but simpler.
+ // Mainly because boost::next uses an MPL file
+ // which causes warnings.
+
+ template <typename Iterator> Iterator next(Iterator it) { return ++it; }
+
+ template <typename Iterator, typename IntType>
+ Iterator next(Iterator it, IntType x)
+ {
+ std::advance(it,
+ static_cast<typename std::iterator_traits<Iterator>::difference_type>(x));
+ return it;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/input_iterator.hpp b/src/boost/libs/unordered/test/helpers/input_iterator.hpp
new file mode 100644
index 000000000..7a938a50f
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/input_iterator.hpp
@@ -0,0 +1,165 @@
+
+// Copyright 2005-2010 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)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
+
+#include <boost/config.hpp>
+#include <iterator>
+
+namespace test {
+ template <class Iterator> struct proxy
+ {
+ typedef typename Iterator::value_type value_type;
+
+ explicit proxy(value_type const& v) : v_(v) {}
+ proxy(proxy const& x) : v_(x.v_) {}
+ operator value_type const&() const { return v_; }
+
+ value_type v_;
+
+ private:
+ proxy& operator=(proxy const&);
+ };
+
+ template <class Iterator> struct input_iterator_adaptor
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+ typedef typename std::iterator_traits<Iterator>::pointer pointer;
+ typedef proxy<Iterator> reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::input_iterator_tag iterator_category;
+
+ 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)
+ {
+ return input_iterator_adaptor<Iterator>(it);
+ }
+
+ template <class Iterator> struct copy_iterator_adaptor
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+ typedef
+ typename std::iterator_traits<Iterator>::difference_type difference_type;
+ typedef typename std::iterator_traits<Iterator>::iterator_category
+ iterator_category;
+ typedef typename std::iterator_traits<Iterator>::pointer pointer;
+ typedef proxy<Iterator> reference;
+
+ copy_iterator_adaptor() : base_() {}
+ explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {}
+ value_type operator*() const { return *base_; }
+ value_type* operator->() const { return &*base_; }
+ value_type operator[](difference_type d) { return base_[d]; }
+ copy_iterator_adaptor& operator++()
+ {
+ ++base_;
+ return *this;
+ }
+ copy_iterator_adaptor operator++(int)
+ {
+ copy_iterator_adaptor tmp(*this);
+ ++base_;
+ return tmp;
+ }
+ copy_iterator_adaptor& operator--()
+ {
+ --base_;
+ return *this;
+ }
+ copy_iterator_adaptor operator--(int)
+ {
+ copy_iterator_adaptor tmp(*this);
+ --base_;
+ return tmp;
+ }
+ copy_iterator_adaptor operator+=(difference_type x)
+ {
+ base_ += x;
+ return *this;
+ }
+ copy_iterator_adaptor operator-=(difference_type x)
+ {
+ base_ -= x;
+ return *this;
+ }
+ copy_iterator_adaptor operator+(difference_type n)
+ {
+ return copy_iterator_adaptor(base_ + n);
+ }
+ copy_iterator_adaptor operator-(difference_type n)
+ {
+ return copy_iterator_adaptor(base_ - n);
+ }
+ friend copy_iterator_adaptor operator+(
+ difference_type n, copy_iterator_adaptor x)
+ {
+ return x + n;
+ }
+ difference_type operator-(copy_iterator_adaptor const& other)
+ {
+ return base_ - other.base_;
+ }
+ bool operator==(copy_iterator_adaptor const& x) const
+ {
+ return base_ == x.base_;
+ }
+ bool operator!=(copy_iterator_adaptor const& x) const
+ {
+ return base_ != x.base_;
+ }
+ bool operator<(copy_iterator_adaptor const& x) const
+ {
+ return base_ < x.base_;
+ }
+ bool operator>(copy_iterator_adaptor const& x) const
+ {
+ return base_ > x.base_;
+ }
+ bool operator<=(copy_iterator_adaptor const& x) const
+ {
+ return base_ <= x.base_;
+ }
+ bool operator>=(copy_iterator_adaptor const& x) const
+ {
+ return base_ >= x.base_;
+ }
+
+ private:
+ Iterator base_;
+ };
+
+ template <class Iterator>
+ copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
+ {
+ return copy_iterator_adaptor<Iterator>(it);
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/invariants.hpp b/src/boost/libs/unordered/test/helpers/invariants.hpp
new file mode 100644
index 000000000..a555da60c
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/invariants.hpp
@@ -0,0 +1,130 @@
+
+// Copyright 2006-2009 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)
+
+// This header contains metafunctions/functions to get the equivalent
+// associative container for an unordered container, and compare the contents.
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER
+
+#include "./helpers.hpp"
+#include "./metafunctions.hpp"
+#include <cmath>
+#include <set>
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4267) // conversion from 'size_t' to 'unsigned int',
+ // possible loss of data
+#endif
+
+namespace test {
+ template <class X> void check_equivalent_keys(X const& x1)
+ {
+ typename X::key_equal eq = x1.key_eq();
+ typedef typename X::key_type key_type;
+ std::set<key_type, std::less<key_type> > found_;
+
+ typename X::const_iterator it = x1.begin(), end = x1.end();
+ typename X::size_type size = 0;
+ while (it != end) {
+ // First test that the current key has not occurred before, required
+ // to test either that keys are unique or that equivalent keys are
+ // adjacent. (6.3.1/6)
+ key_type key = get_key<X>(*it);
+ if (!found_.insert(key).second)
+ BOOST_ERROR("Elements with equivalent keys aren't adjacent.");
+
+ // Iterate over equivalent keys, counting them.
+ unsigned int count = 0;
+ do {
+ ++it;
+ ++count;
+ ++size;
+ } while (it != end && eq(get_key<X>(*it), key));
+
+ // If the container has unique keys, test that there's only one.
+ // Since the previous test makes sure that all equivalent keys are
+ // adjacent, this is all the equivalent keys - so the test is
+ // sufficient. (6.3.1/6 again).
+ if (test::has_unique_keys<X>::value && count != 1)
+ BOOST_ERROR("Non-unique key.");
+
+ if (x1.count(key) != count) {
+ BOOST_ERROR("Incorrect output of count.");
+ std::cerr << x1.count(key) << "," << count << "\n";
+ }
+
+ // Check that the keys are in the correct bucket and are
+ // adjacent in the bucket.
+ typename X::size_type bucket = x1.bucket(key);
+ typename X::const_local_iterator lit = x1.begin(bucket),
+ lend = x1.end(bucket);
+
+ unsigned int count_checked = 0;
+ for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
+ ++count_checked;
+ }
+
+ if (lit == lend) {
+ BOOST_ERROR("Unable to find element with a local_iterator");
+ std::cerr << "Checked: " << count_checked << " elements" << std::endl;
+ } else {
+ unsigned int count2 = 0;
+ for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
+ ++count2;
+ if (count != count2)
+ BOOST_ERROR("Element count doesn't match local_iterator.");
+ for (; lit != lend; ++lit) {
+ if (eq(get_key<X>(*lit), key)) {
+ BOOST_ERROR("Non-adjacent element with equivalent key "
+ "in bucket.");
+ break;
+ }
+ }
+ }
+ };
+
+ // Check that size matches up.
+
+ if (x1.size() != size) {
+ BOOST_ERROR("x1.size() doesn't match actual size.");
+ std::cout << x1.size() << "/" << size << std::endl;
+ }
+
+ // Check the load factor.
+
+ float load_factor = size == 0 ? 0
+ : static_cast<float>(size) /
+ static_cast<float>(x1.bucket_count());
+ using namespace std;
+ if (fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
+ BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
+
+ // Check that size in the buckets matches up.
+
+ typename X::size_type bucket_size = 0;
+
+ for (typename X::size_type i = 0; i < x1.bucket_count(); ++i) {
+ for (typename X::const_local_iterator begin2 = x1.begin(i),
+ end2 = x1.end(i);
+ begin2 != end2; ++begin2) {
+ ++bucket_size;
+ }
+ }
+
+ if (x1.size() != bucket_size) {
+ BOOST_ERROR("x1.size() doesn't match bucket size.");
+ std::cout << x1.size() << "/" << bucket_size << std::endl;
+ }
+ }
+}
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/list.hpp b/src/boost/libs/unordered/test/helpers/list.hpp
new file mode 100644
index 000000000..d39c766e7
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/list.hpp
@@ -0,0 +1,327 @@
+
+// Copyright 2008-2009 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)
+
+// Gratuitous single linked list.
+//
+// Sadly some STL implementations aren't up to scratch and I need a simple
+// cross-platform container. So here it is.
+
+#if !defined(UNORDERED_TEST_LIST_HEADER)
+#define UNORDERED_TEST_LIST_HEADER
+
+#include <boost/limits.hpp>
+#include <functional>
+#include <iterator>
+
+namespace test {
+ template <typename It1, typename It2>
+ bool equal(It1 begin, It1 end, It2 compare)
+ {
+ for (; begin != end; ++begin, ++compare)
+ if (*begin != *compare)
+ return false;
+ return true;
+ }
+
+ template <typename It1, typename It2, typename Pred>
+ bool equal(It1 begin, It1 end, It2 compare, Pred predicate)
+ {
+ for (; begin != end; ++begin, ++compare)
+ if (!predicate(*begin, *compare))
+ return false;
+ return true;
+ }
+
+ template <typename T> class list;
+
+ namespace test_detail {
+ template <typename T> class list_node;
+ template <typename T> class list_data;
+ template <typename T> class list_iterator;
+ template <typename T> class list_const_iterator;
+
+ template <typename T> class list_node
+ {
+ list_node(list_node const&);
+ list_node& operator=(list_node const&);
+
+ public:
+ T value_;
+ list_node* next_;
+
+ list_node(T const& v) : value_(v), next_(0) {}
+ list_node(T const& v, list_node* n) : value_(v), next_(n) {}
+ };
+
+ template <typename T> class list_data
+ {
+ public:
+ typedef list_node<T> node;
+ typedef unsigned int size_type;
+
+ node* first_;
+ node** last_ptr_;
+ size_type size_;
+
+ list_data() : first_(0), last_ptr_(&first_), size_(0) {}
+
+ ~list_data()
+ {
+ while (first_) {
+ node* tmp = first_;
+ first_ = first_->next_;
+ delete tmp;
+ }
+ }
+
+ private:
+ list_data(list_data const&);
+ list_data& operator=(list_data const&);
+ };
+
+ template <typename T> class list_iterator
+ {
+ friend class list_const_iterator<T>;
+ friend class test::list<T>;
+ typedef list_node<T> node;
+ typedef list_const_iterator<T> const_iterator;
+
+ node* ptr_;
+
+ public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef int difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ list_iterator() : ptr_(0) {}
+ explicit list_iterator(node* x) : ptr_(x) {}
+
+ T& operator*() const { return ptr_->value_; }
+ T* operator->() const { return &ptr_->value_; }
+ list_iterator& operator++()
+ {
+ ptr_ = ptr_->next_;
+ return *this;
+ }
+ list_iterator operator++(int)
+ {
+ list_iterator tmp = *this;
+ ptr_ = ptr_->next_;
+ return tmp;
+ }
+ bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
+ bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
+ };
+
+ template <typename T> class list_const_iterator
+ {
+ friend class list_iterator<T>;
+ friend class test::list<T>;
+ typedef list_node<T> node;
+ typedef list_iterator<T> iterator;
+ typedef list_const_iterator<T> const_iterator;
+
+ node* ptr_;
+
+ public:
+ typedef T value_type;
+ typedef T const* pointer;
+ typedef T const& reference;
+ typedef int difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ list_const_iterator() : ptr_(0) {}
+ list_const_iterator(list_iterator<T> const& x) : ptr_(x.ptr_) {}
+
+ T const& operator*() const { return ptr_->value_; }
+ T const* operator->() const { return &ptr_->value_; }
+
+ list_const_iterator& operator++()
+ {
+ ptr_ = ptr_->next_;
+ return *this;
+ }
+
+ list_const_iterator operator++(int)
+ {
+ list_const_iterator tmp = *this;
+ ptr_ = ptr_->next_;
+ return tmp;
+ }
+
+ bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
+
+ bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
+ };
+ }
+
+ template <typename T> class list
+ {
+ typedef test::test_detail::list_data<T> data;
+ typedef test::test_detail::list_node<T> node;
+ data data_;
+
+ public:
+ typedef T value_type;
+ typedef value_type& reference;
+ typedef value_type const& const_reference;
+ typedef unsigned int size_type;
+
+ typedef test::test_detail::list_iterator<T> iterator;
+ typedef test::test_detail::list_const_iterator<T> const_iterator;
+
+ list() : data_() {}
+
+ list(list const& other) : data_() { insert(other.begin(), other.end()); }
+
+ template <class InputIterator>
+ list(InputIterator i, InputIterator j) : data_()
+ {
+ insert(i, j);
+ }
+
+ list& operator=(list const& other)
+ {
+ clear();
+ insert(other.begin(), other.end());
+ return *this;
+ }
+
+ iterator begin() { return iterator(data_.first_); }
+ iterator end() { return iterator(); }
+ const_iterator begin() const { return iterator(data_.first_); }
+ const_iterator end() const { return iterator(); }
+ const_iterator cbegin() const { return iterator(data_.first_); }
+ const_iterator cend() const { return iterator(); }
+
+ template <class InputIterator> void insert(InputIterator i, InputIterator j)
+ {
+ for (; i != j; ++i)
+ push_back(*i);
+ }
+
+ void push_front(value_type const& v)
+ {
+ data_.first_ = new node(v, data_.first_);
+ if (!data_.size_)
+ data_.last_ptr_ = &(*data_.last_ptr_)->next_;
+ ++data_.size_;
+ }
+
+ void push_back(value_type const& v)
+ {
+ *data_.last_ptr_ = new node(v);
+ data_.last_ptr_ = &(*data_.last_ptr_)->next_;
+ ++data_.size_;
+ }
+
+ void clear()
+ {
+ while (data_.first_) {
+ node* tmp = data_.first_;
+ data_.first_ = data_.first_->next_;
+ --data_.size_;
+ delete tmp;
+ }
+ data_.last_ptr_ = &data_.first_;
+ }
+
+ void erase(const_iterator i, const_iterator j)
+ {
+ node** ptr = &data_.first_;
+
+ while (*ptr != i.ptr_) {
+ ptr = &(*ptr)->next_;
+ }
+
+ while (*ptr != j.ptr_) {
+ node* to_delete = *ptr;
+ *ptr = (*ptr)->next_;
+ --data_.size_;
+ delete to_delete;
+ }
+
+ if (!*ptr)
+ data_.last_ptr_ = ptr;
+ }
+
+ bool empty() const { return !data_.size_; }
+
+ size_type size() const { return data_.size_; }
+
+ void sort() { sort(std::less<T>()); }
+
+ template <typename Less> void sort(Less less = Less())
+ {
+ if (!empty())
+ merge_sort(
+ &data_.first_, (std::numeric_limits<size_type>::max)(), less);
+ }
+
+ bool operator==(list const& y) const
+ {
+ return size() == y.size() && test::equal(begin(), end(), y.begin());
+ }
+
+ bool operator!=(list const& y) const { return !(*this == y); }
+
+ private:
+ template <typename Less>
+ node** merge_sort(node** l, size_type recurse_limit, Less less)
+ {
+ node** ptr = &(*l)->next_;
+ for (size_type count = 0; count < recurse_limit && *ptr; ++count) {
+ ptr = merge_adjacent_ranges(l, ptr, merge_sort(ptr, count, less), less);
+ }
+ return ptr;
+ }
+
+ template <typename Less>
+ node** merge_adjacent_ranges(
+ node** first, node** second, node** third, Less less)
+ {
+ for (;;) {
+ for (;;) {
+ if (first == second)
+ return third;
+ if (less((*second)->value_, (*first)->value_))
+ break;
+ first = &(*first)->next_;
+ }
+
+ swap_adjacent_ranges(first, second, third);
+ first = &(*first)->next_;
+
+ // Since the two ranges we just swapped, the order is now:
+ // first...third...second
+
+ for (;;) {
+ if (first == third)
+ return second;
+ if (!less((*first)->value_, (*third)->value_))
+ break;
+ first = &(*first)->next_;
+ }
+
+ swap_adjacent_ranges(first, third, second);
+ first = &(*first)->next_;
+ }
+ }
+
+ void swap_adjacent_ranges(node** first, node** second, node** third)
+ {
+ node* tmp = *first;
+ *first = *second;
+ *second = *third;
+ *third = tmp;
+ if (!*second)
+ data_.last_ptr_ = second;
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/memory.hpp b/src/boost/libs/unordered/test/helpers/memory.hpp
new file mode 100644
index 000000000..22946cc25
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/memory.hpp
@@ -0,0 +1,189 @@
+
+// Copyright 2006-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_MEMORY_HEADER)
+#define BOOST_UNORDERED_TEST_MEMORY_HEADER
+
+#include "../helpers/test.hpp"
+#include <boost/assert.hpp>
+#include <boost/unordered/detail/implementation.hpp>
+#include <map>
+#include <memory>
+
+namespace test {
+ namespace detail {
+ struct memory_area
+ {
+ void const* start;
+ void const* end;
+
+ memory_area(void const* s, void const* e) : start(s), end(e)
+ {
+ BOOST_ASSERT(start != end);
+ }
+ };
+
+ struct memory_track
+ {
+ explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {}
+
+ int constructed_;
+ int tag_;
+ };
+
+ // This is a bit dodgy as it defines overlapping
+ // areas as 'equal', so this isn't a total ordering.
+ // But it is for non-overlapping memory regions - which
+ // is what'll be stored.
+ //
+ // All searches will be for areas entirely contained by
+ // a member of the set - so it should find the area that contains
+ // the region that is searched for.
+
+ struct memory_area_compare
+ {
+ bool operator()(memory_area const& x, memory_area const& y) const
+ {
+ return x.end <= y.start;
+ }
+ };
+
+ struct memory_tracker
+ {
+ typedef std::map<memory_area, memory_track, memory_area_compare,
+ std::allocator<std::pair<memory_area const, memory_track> > >
+ allocated_memory_type;
+
+ allocated_memory_type allocated_memory;
+ unsigned int count_allocators;
+ unsigned int count_allocations;
+ unsigned int count_constructions;
+ bool tracking_constructions;
+
+ memory_tracker()
+ : count_allocators(0), count_allocations(0), count_constructions(0),
+ tracking_constructions(true)
+ {
+ }
+
+ ~memory_tracker() { BOOST_TEST(count_allocators == 0); }
+
+ void allocator_ref()
+ {
+ if (count_allocators == 0) {
+ count_allocations = 0;
+ count_constructions = 0;
+ allocated_memory.clear();
+ }
+ ++count_allocators;
+ }
+
+ void allocator_unref()
+ {
+ BOOST_TEST(count_allocators > 0);
+ if (count_allocators > 0) {
+ --count_allocators;
+ if (count_allocators == 0) {
+ bool no_allocations_left = (count_allocations == 0);
+ bool no_constructions_left = (count_constructions == 0);
+ bool allocated_memory_empty = allocated_memory.empty();
+
+ // Clearing the data before the checks terminate the
+ // tests.
+ count_allocations = 0;
+ count_constructions = 0;
+ allocated_memory.clear();
+
+ BOOST_TEST(no_allocations_left);
+ BOOST_TEST(no_constructions_left);
+ BOOST_TEST(allocated_memory_empty);
+ }
+ }
+ }
+
+ void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag)
+ {
+ if (n == 0) {
+ BOOST_ERROR("Allocating 0 length array.");
+ } else {
+ ++count_allocations;
+ allocated_memory.insert(std::pair<memory_area const, memory_track>(
+ memory_area(ptr, (char*)ptr + n * size), memory_track(tag)));
+ }
+ }
+
+ void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag,
+ bool check_tag_ = true)
+ {
+ allocated_memory_type::iterator pos =
+ allocated_memory.find(memory_area(ptr, (char*)ptr + n * size));
+ if (pos == allocated_memory.end()) {
+ BOOST_ERROR("Deallocating unknown pointer.");
+ } else {
+ BOOST_TEST(pos->first.start == ptr);
+ BOOST_TEST(pos->first.end == (char*)ptr + n * size);
+ if (check_tag_)
+ BOOST_TEST(pos->second.tag_ == tag);
+ allocated_memory.erase(pos);
+ }
+ BOOST_TEST(count_allocations > 0);
+ if (count_allocations > 0)
+ --count_allocations;
+ }
+
+ void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
+ {
+ if (tracking_constructions) {
+ ++count_constructions;
+ }
+ }
+
+ void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
+ {
+ if (tracking_constructions) {
+ BOOST_TEST(count_constructions > 0);
+ if (count_constructions > 0)
+ --count_constructions;
+ }
+ }
+ };
+ }
+
+ namespace detail {
+ // This won't be a problem as I'm only using a single compile unit
+ // in each test (this is actually required by the minimal test
+ // framework).
+ //
+ // boostinspect:nounnamed
+ namespace {
+ test::detail::memory_tracker tracker;
+ }
+ }
+
+ namespace detail {
+ struct disable_construction_tracking
+ {
+ bool old_value;
+
+ disable_construction_tracking()
+ : old_value(detail::tracker.tracking_constructions)
+ {
+ test::detail::tracker.tracking_constructions = false;
+ }
+
+ ~disable_construction_tracking()
+ {
+ test::detail::tracker.tracking_constructions = old_value;
+ }
+
+ private:
+ disable_construction_tracking(disable_construction_tracking const&);
+ disable_construction_tracking& operator=(
+ disable_construction_tracking const&);
+ };
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/metafunctions.hpp b/src/boost/libs/unordered/test/helpers/metafunctions.hpp
new file mode 100644
index 000000000..f5f138514
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/metafunctions.hpp
@@ -0,0 +1,30 @@
+
+// Copyright 2005-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_METAFUNCTIONS_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_METAFUNCTIONS_HEADER
+
+#include <boost/config.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace test {
+ template <class Container>
+ struct is_set : public boost::is_same<typename Container::key_type,
+ typename Container::value_type>
+ {
+ };
+
+ template <class Container> struct has_unique_keys
+ {
+ static char flip(typename Container::iterator const&);
+ static long flip(std::pair<typename Container::iterator, bool> const&);
+ BOOST_STATIC_CONSTANT(bool,
+ value = sizeof(long) ==
+ sizeof(flip(
+ ((Container*)0)->insert(*(typename Container::value_type*)0))));
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/postfix.hpp b/src/boost/libs/unordered/test/helpers/postfix.hpp
new file mode 100644
index 000000000..ca14ae71b
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/postfix.hpp
@@ -0,0 +1,10 @@
+
+// Copyright 2012 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 this after the boost headers, but before other test headers.
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/prefix.hpp b/src/boost/libs/unordered/test/helpers/prefix.hpp
new file mode 100644
index 000000000..fe7570250
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/prefix.hpp
@@ -0,0 +1,11 @@
+
+// Copyright 2009 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)
+
+#if defined(_WIN32_WCE)
+// The standard windows mobile headers trigger this warning so I disable it
+// before doing anything else.
+#pragma warning(disable : 4201) // nonstandard extension used :
+ // nameless struct/union
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/random_values.hpp b/src/boost/libs/unordered/test/helpers/random_values.hpp
new file mode 100644
index 000000000..d139d1804
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/random_values.hpp
@@ -0,0 +1,109 @@
+
+// Copyright 2005-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER
+
+#include "./generators.hpp"
+#include "./list.hpp"
+#include "./metafunctions.hpp"
+#include <algorithm>
+#include <boost/detail/select_type.hpp>
+
+namespace test {
+ template <class X> struct unordered_generator_set
+ {
+ typedef typename X::value_type value_type;
+
+ random_generator type_;
+
+ unordered_generator_set(random_generator type) : type_(type) {}
+
+ template <class T> void fill(T& x, std::size_t len)
+ {
+ value_type* value_ptr = 0;
+ len += x.size();
+
+ for (std::size_t i = 0; i < len; ++i) {
+ value_type value = generate(value_ptr, type_);
+
+ std::size_t count =
+ type_ == generate_collisions ? random_value(5) + 1 : 1;
+
+ for (std::size_t j = 0; j < count; ++j) {
+ x.push_back(value);
+ }
+ }
+ }
+ };
+
+ template <class X> struct unordered_generator_map
+ {
+ typedef typename X::key_type key_type;
+ typedef typename X::mapped_type mapped_type;
+
+ random_generator type_;
+
+ unordered_generator_map(random_generator type) : type_(type) {}
+
+ template <class T> void fill(T& x, std::size_t len)
+ {
+ key_type* key_ptr = 0;
+ mapped_type* mapped_ptr = 0;
+
+ for (std::size_t i = 0; i < len; ++i) {
+ key_type key = generate(key_ptr, type_);
+
+ std::size_t count =
+ type_ == generate_collisions ? random_value(5) + 1 : 1;
+
+ for (std::size_t j = 0; j < count; ++j) {
+ x.push_back(std::pair<key_type const, mapped_type>(
+ key, generate(mapped_ptr, type_)));
+ }
+ }
+ }
+ };
+
+ template <class X>
+ struct unordered_generator_base
+ : public boost::detail::if_true<test::is_set<X>::value>::
+ BOOST_NESTED_TEMPLATE then<test::unordered_generator_set<X>,
+ test::unordered_generator_map<X> >
+ {
+ };
+
+ template <class X>
+ struct unordered_generator : public unordered_generator_base<X>::type
+ {
+ typedef typename unordered_generator_base<X>::type base;
+
+ unordered_generator(random_generator const& type = default_generator)
+ : base(type)
+ {
+ }
+ };
+
+ template <class X>
+ struct random_values : public test::list<typename X::value_type>
+ {
+ random_values() {}
+
+ explicit random_values(std::size_t count,
+ test::random_generator const& generator = test::default_generator)
+ {
+ fill(count, generator);
+ }
+
+ void fill(std::size_t count,
+ test::random_generator const& generator = test::default_generator)
+ {
+ test::unordered_generator<X> gen(generator);
+ gen.fill(*this, count);
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/strong.hpp b/src/boost/libs/unordered/test/helpers/strong.hpp
new file mode 100644
index 000000000..3c9361337
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/strong.hpp
@@ -0,0 +1,42 @@
+
+// Copyright 2005-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER
+
+#include "./equivalent.hpp"
+#include "./exception_test.hpp"
+#include "./list.hpp"
+#include <boost/config.hpp>
+#include <iterator>
+
+namespace test {
+ template <class X> class strong
+ {
+ typedef test::list<typename X::value_type> values_type;
+ values_type values_;
+ unsigned int allocations_;
+
+ public:
+ void store(X const& x, unsigned int allocations = 0)
+ {
+ DISABLE_EXCEPTIONS;
+ values_.clear();
+ values_.insert(x.cbegin(), x.cend());
+ allocations_ = allocations;
+ }
+
+ void test(X const& x, unsigned int allocations = 0) const
+ {
+ if (!(x.size() == values_.size() && test::equal(x.cbegin(), x.cend(),
+ values_.begin(), test::equivalent)))
+ BOOST_ERROR("Strong exception safety failure.");
+ if (allocations != allocations_)
+ BOOST_ERROR("Strong exception failure: extra allocations.");
+ }
+ };
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/test.hpp b/src/boost/libs/unordered/test/helpers/test.hpp
new file mode 100644
index 000000000..5534f8118
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/test.hpp
@@ -0,0 +1,201 @@
+
+// Copyright 2006-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_TEST_HEADER)
+#define BOOST_UNORDERED_TEST_TEST_HEADER
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#define UNORDERED_AUTO_TEST(x) \
+ struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
+ { \
+ BOOST_PP_CAT(x, _type) \
+ () : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
+ { \
+ ::test::get_state().add_test(this); \
+ } \
+ void run(); \
+ }; \
+ BOOST_PP_CAT(x, _type) x; \
+ void BOOST_PP_CAT(x, _type)::run()
+
+#define RUN_TESTS() \
+ int main(int, char**) \
+ { \
+ BOOST_UNORDERED_TEST_COMPILER_INFO() \
+ ::test::get_state().run_tests(); \
+ return boost::report_errors(); \
+ }
+
+#define RUN_TESTS_QUIET() \
+ int main(int, char**) \
+ { \
+ BOOST_UNORDERED_TEST_COMPILER_INFO() \
+ ::test::get_state().run_tests(true); \
+ return boost::report_errors(); \
+ }
+
+#define UNORDERED_SUB_TEST(x) \
+ for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \
+ UNORDERED_SUB_TEST_VALUE; \
+ UNORDERED_SUB_TEST_VALUE = \
+ ::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE))
+
+namespace test {
+
+ struct registered_test_base
+ {
+ registered_test_base* next;
+ char const* name;
+ explicit registered_test_base(char const* n) : name(n) {}
+ virtual void run() = 0;
+ virtual ~registered_test_base() {}
+ };
+
+ struct state
+ {
+ bool is_quiet;
+ registered_test_base* first_test;
+ registered_test_base* last_test;
+
+ state() : is_quiet(false), first_test(0), last_test(0) {}
+
+ void add_test(registered_test_base* test)
+ {
+ if (last_test) {
+ last_test->next = test;
+ } else {
+ first_test = test;
+ }
+ last_test = test;
+ }
+
+ void run_tests(bool quiet = false)
+ {
+ is_quiet = quiet;
+
+ for (registered_test_base* i = first_test; i; i = i->next) {
+ int error_count = boost::detail::test_errors();
+ if (!quiet) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Running " << i->name << "\n"
+ << std::flush;
+ }
+ i->run();
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::flush;
+ if (quiet && error_count != boost::detail::test_errors()) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in: " << i->name << "\n"
+ << std::flush;
+ }
+ }
+ }
+
+ int start_sub_test(char const* name)
+ {
+ if (!is_quiet) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Sub-test: " << name << "\n"
+ << std::flush;
+ }
+ // Add one because it's used as a loop condition.
+ return boost::detail::test_errors() + 1;
+ }
+
+ int end_sub_test(char const* name, int value)
+ {
+ if (is_quiet && value != boost::detail::test_errors() + 1) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in sub-test: " << name << "\n"
+ << std::flush;
+ }
+ return 0;
+ }
+ };
+
+ // Get the currnet translation unit's test state.
+ static inline state& get_state()
+ {
+ static state instance;
+ return instance;
+ }
+}
+
+#if defined(__cplusplus)
+#define BOOST_UNORDERED_CPLUSPLUS __cplusplus
+#else
+#define BOOST_UNORDERED_CPLUSPLUS "(not defined)"
+#endif
+
+#define BOOST_UNORDERED_TEST_COMPILER_INFO() \
+ { \
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
+ << "Compiler: " << BOOST_COMPILER << "\n" \
+ << "Library: " << BOOST_STDLIB << "\n" \
+ << "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \
+ << "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \
+ << BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
+ << "BOOST_UNORDERED_EMPLACE_LIMIT: " << BOOST_UNORDERED_EMPLACE_LIMIT \
+ << "\n" \
+ << "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \
+ << BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \
+ << "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
+ << BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \
+ << std::flush; \
+ }
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/seq/fold_left.hpp>
+#include <boost/preprocessor/seq/for_each_product.hpp>
+#include <boost/preprocessor/seq/seq.hpp>
+#include <boost/preprocessor/seq/to_tuple.hpp>
+
+// Run test with every combination of the parameters (a sequence of sequences)
+#define UNORDERED_TEST(name, parameters) \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((1))parameters)
+
+#define UNORDERED_TEST_REPEAT(name, n, parameters) \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((n))parameters)
+
+#define UNORDERED_TEST_OP(r, product) \
+ UNORDERED_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
+ BOOST_PP_SEQ_ELEM(1, product), \
+ BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
+
+#define UNORDERED_TEST_OP2(name, n, params) \
+ UNORDERED_AUTO_TEST ( \
+ BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) { \
+ for (int i = 0; i < n; ++i) \
+ name BOOST_PP_SEQ_TO_TUPLE(params); \
+ }
+
+#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
+ BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
+
+#define UNORDERED_MULTI_TEST(name, impl, parameters) \
+ UNORDERED_MULTI_TEST_REPEAT(name, impl, 1, parameters)
+
+#define UNORDERED_MULTI_TEST_REPEAT(name, impl, n, parameters) \
+ UNORDERED_AUTO_TEST (name) { \
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
+ UNORDERED_MULTI_TEST_OP, ((impl))((n))parameters) \
+ }
+
+#define UNORDERED_MULTI_TEST_OP(r, product) \
+ UNORDERED_MULTI_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
+ BOOST_PP_SEQ_ELEM(1, product), \
+ BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
+
+// Need to wrap UNORDERED_SUB_TEST in a block to avoid an msvc bug.
+// https://support.microsoft.com/en-gb/help/315481/bug-too-many-unnested-loops-incorrectly-causes-a-c1061-compiler-error-in-visual-c
+#define UNORDERED_MULTI_TEST_OP2(name, n, params) \
+ { \
+ UNORDERED_SUB_TEST(BOOST_PP_STRINGIZE( \
+ BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params))) \
+ { \
+ for (int i = 0; i < n; ++i) \
+ name BOOST_PP_SEQ_TO_TUPLE(params); \
+ } \
+ }
+
+#endif
diff --git a/src/boost/libs/unordered/test/helpers/tracker.hpp b/src/boost/libs/unordered/test/helpers/tracker.hpp
new file mode 100644
index 000000000..0f86ba6f7
--- /dev/null
+++ b/src/boost/libs/unordered/test/helpers/tracker.hpp
@@ -0,0 +1,138 @@
+
+// Copyright 2006-2009 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)
+
+// This header contains metafunctions/functions to get the equivalent
+// associative container for an unordered container, and compare the contents.
+
+#if !defined(BOOST_UNORDERED_TEST_HELPERS_TRACKER_HEADER)
+#define BOOST_UNORDERED_TEST_HELPERS_TRACKER_HEADER
+
+#include "../objects/fwd.hpp"
+#include "./equivalent.hpp"
+#include "./helpers.hpp"
+#include "./list.hpp"
+#include "./metafunctions.hpp"
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <set>
+
+namespace test {
+ template <typename X> struct equals_to_compare
+ {
+ typedef std::less<typename X::first_argument_type> type;
+ };
+
+ template <> struct equals_to_compare<test::equal_to>
+ {
+ typedef test::less type;
+ };
+
+ template <class X1, class X2> void compare_range(X1 const& x1, X2 const& x2)
+ {
+ typedef test::list<typename X1::value_type> value_list;
+ value_list values1(x1.begin(), x1.end());
+ value_list values2(x2.begin(), x2.end());
+ values1.sort();
+ values2.sort();
+ BOOST_TEST(values1.size() == values2.size() &&
+ test::equal(values1.begin(), values1.end(), values2.begin(),
+ test::equivalent));
+ }
+
+ template <class X1, class X2, class T>
+ void compare_pairs(X1 const& x1, X2 const& x2, T*)
+ {
+ test::list<T> values1(x1.first, x1.second);
+ test::list<T> values2(x2.first, x2.second);
+ values1.sort();
+ values2.sort();
+ BOOST_TEST(values1.size() == values2.size() &&
+ test::equal(values1.begin(), values1.end(), values2.begin(),
+ test::equivalent));
+ }
+
+ template <typename X, bool is_set = test::is_set<X>::value,
+ bool has_unique_keys = test::has_unique_keys<X>::value>
+ struct ordered_base;
+
+ template <typename X> struct ordered_base<X, true, true>
+ {
+ typedef std::set<typename X::value_type,
+ typename equals_to_compare<typename X::key_equal>::type>
+ type;
+ };
+
+ template <typename X> struct ordered_base<X, true, false>
+ {
+ typedef std::multiset<typename X::value_type,
+ typename equals_to_compare<typename X::key_equal>::type>
+ type;
+ };
+
+ template <typename X> struct ordered_base<X, false, true>
+ {
+ typedef std::map<typename X::key_type, typename X::mapped_type,
+ typename equals_to_compare<typename X::key_equal>::type>
+ type;
+ };
+
+ template <typename X> struct ordered_base<X, false, false>
+ {
+ typedef std::multimap<typename X::key_type, typename X::mapped_type,
+ typename equals_to_compare<typename X::key_equal>::type>
+ type;
+ };
+
+ template <class X> class ordered : public ordered_base<X>::type
+ {
+ typedef typename ordered_base<X>::type base;
+
+ public:
+ typedef typename base::key_compare key_compare;
+
+ ordered() : base() {}
+
+ explicit ordered(key_compare const& kc) : base(kc) {}
+
+ void compare(X const& x) { compare_range(x, *this); }
+
+ void compare_key(X const& x, typename X::value_type const& val)
+ {
+ compare_pairs(x.equal_range(get_key<X>(val)),
+ this->equal_range(get_key<X>(val)), (typename X::value_type*)0);
+ }
+
+ template <class It> void insert_range(It b, It e)
+ {
+ while (b != e) {
+ this->insert(*b);
+ ++b;
+ }
+ }
+ };
+
+ template <class Equals>
+ typename equals_to_compare<Equals>::type create_compare(Equals const&)
+ {
+ typename equals_to_compare<Equals>::type x;
+ return x;
+ }
+
+ template <class X> ordered<X> create_ordered(X const& container)
+ {
+ return ordered<X>(create_compare(container.key_eq()));
+ }
+
+ template <class X1, class X2>
+ void check_container(X1 const& container, X2 const& values)
+ {
+ ordered<X1> tracker = create_ordered(container);
+ tracker.insert_range(values.begin(), values.end());
+ tracker.compare(container);
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/objects/cxx11_allocator.hpp b/src/boost/libs/unordered/test/objects/cxx11_allocator.hpp
new file mode 100644
index 000000000..e96f8d944
--- /dev/null
+++ b/src/boost/libs/unordered/test/objects/cxx11_allocator.hpp
@@ -0,0 +1,344 @@
+
+// Copyright 2006-2011 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)
+
+#if !defined(BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER)
+#define BOOST_UNORDERED_TEST_CXX11_ALLOCATOR_HEADER
+
+#include <boost/config.hpp>
+#include <boost/limits.hpp>
+#include <cstddef>
+
+#include "../helpers/fwd.hpp"
+#include "../helpers/memory.hpp"
+
+namespace test {
+ struct allocator_false
+ {
+ enum
+ {
+ is_select_on_copy = 0,
+ is_propagate_on_swap = 0,
+ is_propagate_on_assign = 0,
+ is_propagate_on_move = 0,
+ cxx11_construct = 0
+ };
+ };
+
+ struct allocator_flags_all
+ {
+ enum
+ {
+ is_select_on_copy = 1,
+ is_propagate_on_swap = 1,
+ is_propagate_on_assign = 1,
+ is_propagate_on_move = 1,
+ cxx11_construct = 1
+ };
+ };
+
+ struct select_copy : allocator_false
+ {
+ enum
+ {
+ is_select_on_copy = 1
+ };
+ };
+ struct propagate_swap : allocator_false
+ {
+ enum
+ {
+ is_propagate_on_swap = 1
+ };
+ };
+ struct propagate_assign : allocator_false
+ {
+ enum
+ {
+ is_propagate_on_assign = 1
+ };
+ };
+ struct propagate_move : allocator_false
+ {
+ enum
+ {
+ is_propagate_on_move = 1
+ };
+ };
+
+ struct no_select_copy : allocator_flags_all
+ {
+ enum
+ {
+ is_select_on_copy = 0
+ };
+ };
+ struct no_propagate_swap : allocator_flags_all
+ {
+ enum
+ {
+ is_propagate_on_swap = 0
+ };
+ };
+ struct no_propagate_assign : allocator_flags_all
+ {
+ enum
+ {
+ is_propagate_on_assign = 0
+ };
+ };
+ struct no_propagate_move : allocator_flags_all
+ {
+ enum
+ {
+ is_propagate_on_move = 0
+ };
+ };
+
+ template <typename Flag> struct swap_allocator_base
+ {
+ struct propagate_on_container_swap
+ {
+ enum
+ {
+ value = Flag::is_propagate_on_swap
+ };
+ };
+ };
+
+ template <typename Flag> struct assign_allocator_base
+ {
+ struct propagate_on_container_copy_assignment
+ {
+ enum
+ {
+ value = Flag::is_propagate_on_assign
+ };
+ };
+ };
+
+ template <typename Flag> struct move_allocator_base
+ {
+ struct propagate_on_container_move_assignment
+ {
+ enum
+ {
+ value = Flag::is_propagate_on_move
+ };
+ };
+ };
+
+ namespace {
+ // boostinspect:nounnamed
+ bool force_equal_allocator_value = false;
+ }
+
+ struct force_equal_allocator
+ {
+ bool old_value_;
+
+ explicit force_equal_allocator(bool value)
+ : old_value_(force_equal_allocator_value)
+ {
+ force_equal_allocator_value = value;
+ }
+
+ ~force_equal_allocator() { force_equal_allocator_value = old_value_; }
+ };
+
+ template <typename T> struct cxx11_allocator_base
+ {
+ int tag_;
+ int selected_;
+
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T const* const_pointer;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef T value_type;
+
+ explicit cxx11_allocator_base(int t) : tag_(t), selected_(0)
+ {
+ detail::tracker.allocator_ref();
+ }
+
+ template <typename Y>
+ cxx11_allocator_base(cxx11_allocator_base<Y> const& x)
+ : tag_(x.tag_), selected_(x.selected_)
+ {
+ detail::tracker.allocator_ref();
+ }
+
+ cxx11_allocator_base(cxx11_allocator_base const& x)
+ : tag_(x.tag_), selected_(x.selected_)
+ {
+ detail::tracker.allocator_ref();
+ }
+
+ ~cxx11_allocator_base() { detail::tracker.allocator_unref(); }
+
+ pointer address(reference r) { return pointer(&r); }
+
+ const_pointer address(const_reference r) { return const_pointer(&r); }
+
+ pointer allocate(size_type n)
+ {
+ pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
+ detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return ptr;
+ }
+
+ pointer allocate(size_type n, void const*)
+ {
+ pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
+ detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return ptr;
+ }
+
+ void deallocate(pointer p, size_type n)
+ {
+ // Only checking tags when propagating swap.
+ // Note that tags will be tested
+ // properly in the normal allocator.
+ detail::tracker.track_deallocate(
+ (void*)p, n, sizeof(T), tag_, !force_equal_allocator_value);
+ ::operator delete((void*)p);
+ }
+
+ void construct(T* p, T const& t)
+ {
+ detail::tracker.track_construct((void*)p, sizeof(T), tag_);
+ new (p) T(t);
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <typename... Args>
+ void construct(T* p, BOOST_FWD_REF(Args)... args)
+ {
+ detail::tracker.track_construct((void*)p, sizeof(T), tag_);
+ new (p) T(boost::forward<Args>(args)...);
+ }
+#endif
+
+ void destroy(T* p)
+ {
+ detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
+ p->~T();
+ }
+
+ size_type max_size() const
+ {
+ return (std::numeric_limits<size_type>::max)();
+ }
+ };
+
+ template <typename T, typename Flags = propagate_swap, typename Enable = void>
+ struct cxx11_allocator;
+
+ template <typename T, typename Flags>
+ struct cxx11_allocator<T, Flags,
+ typename boost::disable_if_c<Flags::is_select_on_copy>::type>
+ : public cxx11_allocator_base<T>,
+ public swap_allocator_base<Flags>,
+ public assign_allocator_base<Flags>,
+ public move_allocator_base<Flags>,
+ Flags
+ {
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
+ template <typename U> struct rebind
+ {
+ typedef cxx11_allocator<U, Flags> other;
+ };
+#endif
+
+ explicit cxx11_allocator(int t = 0) : cxx11_allocator_base<T>(t) {}
+
+ template <typename Y>
+ cxx11_allocator(cxx11_allocator<Y, Flags> const& x)
+ : cxx11_allocator_base<T>(x)
+ {
+ }
+
+ cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {}
+
+ // When not propagating swap, allocators are always equal
+ // to avoid undefined behaviour.
+ bool operator==(cxx11_allocator const& x) const
+ {
+ return force_equal_allocator_value || (this->tag_ == x.tag_);
+ }
+
+ bool operator!=(cxx11_allocator const& x) const { return !(*this == x); }
+ };
+
+ template <typename T, typename Flags>
+ struct cxx11_allocator<T, Flags,
+ typename boost::enable_if_c<Flags::is_select_on_copy>::type>
+ : public cxx11_allocator_base<T>,
+ public swap_allocator_base<Flags>,
+ public assign_allocator_base<Flags>,
+ public move_allocator_base<Flags>,
+ Flags
+ {
+ cxx11_allocator select_on_container_copy_construction() const
+ {
+ cxx11_allocator tmp(*this);
+ ++tmp.selected_;
+ return tmp;
+ }
+
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
+ template <typename U> struct rebind
+ {
+ typedef cxx11_allocator<U, Flags> other;
+ };
+#endif
+
+ explicit cxx11_allocator(int t = 0) : cxx11_allocator_base<T>(t) {}
+
+ template <typename Y>
+ cxx11_allocator(cxx11_allocator<Y, Flags> const& x)
+ : cxx11_allocator_base<T>(x)
+ {
+ }
+
+ cxx11_allocator(cxx11_allocator const& x) : cxx11_allocator_base<T>(x) {}
+
+ // When not propagating swap, allocators are always equal
+ // to avoid undefined behaviour.
+ bool operator==(cxx11_allocator const& x) const
+ {
+ return force_equal_allocator_value || (this->tag_ == x.tag_);
+ }
+
+ bool operator!=(cxx11_allocator const& x) const { return !(*this == x); }
+ };
+
+ template <typename T, typename Flags>
+ bool equivalent_impl(cxx11_allocator<T, Flags> const& x,
+ cxx11_allocator<T, Flags> const& y, test::derived_type)
+ {
+ return x.tag_ == y.tag_;
+ }
+
+ // Function to check how many times an allocator has been selected,
+ // return 0 for other allocators.
+
+ struct convert_from_anything
+ {
+ template <typename T> convert_from_anything(T const&) {}
+ };
+
+ inline int selected_count(convert_from_anything) { return 0; }
+
+ template <typename T, typename Flags>
+ int selected_count(cxx11_allocator<T, Flags> const& x)
+ {
+ return x.selected_;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/objects/exception.hpp b/src/boost/libs/unordered/test/objects/exception.hpp
new file mode 100644
index 000000000..07f343fb9
--- /dev/null
+++ b/src/boost/libs/unordered/test/objects/exception.hpp
@@ -0,0 +1,752 @@
+
+// Copyright 2006-2009 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)
+
+#if !defined(BOOST_UNORDERED_EXCEPTION_TEST_OBJECTS_HEADER)
+#define BOOST_UNORDERED_EXCEPTION_TEST_OBJECTS_HEADER
+
+#include "../helpers/exception_test.hpp"
+
+#include "../helpers/count.hpp"
+#include "../helpers/fwd.hpp"
+#include "../helpers/generators.hpp"
+#include "../helpers/memory.hpp"
+#include "./fwd.hpp"
+#include <boost/limits.hpp>
+#include <cstddef>
+#include <new>
+
+namespace test {
+ namespace exception {
+ class object;
+ class hash;
+ class equal_to;
+ template <class T> class allocator;
+ object generate(object const*, random_generator);
+ std::pair<object, object> generate(
+ std::pair<object, object> const*, random_generator);
+
+ struct true_type
+ {
+ enum
+ {
+ value = true
+ };
+ };
+
+ struct false_type
+ {
+ enum
+ {
+ value = false
+ };
+ };
+
+ class object : private counted_object
+ {
+ public:
+ int tag1_, tag2_;
+
+ explicit object() : tag1_(0), tag2_(0)
+ {
+ UNORDERED_SCOPE(object::object())
+ {
+ UNORDERED_EPOINT("Mock object default constructor.");
+ }
+ }
+
+ explicit object(int t1, int t2 = 0) : tag1_(t1), tag2_(t2)
+ {
+ UNORDERED_SCOPE(object::object(int))
+ {
+ UNORDERED_EPOINT("Mock object constructor by value.");
+ }
+ }
+
+ object(object const& x)
+ : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
+ {
+ UNORDERED_SCOPE(object::object(object))
+ {
+ UNORDERED_EPOINT("Mock object copy constructor.");
+ }
+ }
+
+ ~object()
+ {
+ tag1_ = -1;
+ tag2_ = -1;
+ }
+
+ object& operator=(object const& x)
+ {
+ UNORDERED_SCOPE(object::operator=(object))
+ {
+ tag1_ = x.tag1_;
+ UNORDERED_EPOINT("Mock object assign operator 1.");
+ tag2_ = x.tag2_;
+ // UNORDERED_EPOINT("Mock object assign operator 2.");
+ }
+ return *this;
+ }
+
+ friend bool operator==(object const& x1, object const& x2)
+ {
+ UNORDERED_SCOPE(operator==(object, object))
+ {
+ UNORDERED_EPOINT("Mock object equality operator.");
+ }
+
+ return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
+ }
+
+ friend bool operator!=(object const& x1, object const& x2)
+ {
+ UNORDERED_SCOPE(operator!=(object, object))
+ {
+ UNORDERED_EPOINT("Mock object inequality operator.");
+ }
+
+ return !(x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_);
+ }
+
+ // None of the last few functions are used by the unordered associative
+ // containers - so there aren't any exception points.
+ friend bool operator<(object const& x1, object const& x2)
+ {
+ return x1.tag1_ < x2.tag1_ ||
+ (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
+ }
+
+ friend object generate(object const*, random_generator g)
+ {
+ int* x = 0;
+ return object(::test::generate(x, g), ::test::generate(x, g));
+ }
+
+ friend std::ostream& operator<<(std::ostream& out, object const& o)
+ {
+ return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
+ }
+ };
+
+ std::pair<object, object> generate(
+ std::pair<object, object> const*, random_generator g)
+ {
+ int* x = 0;
+ return std::make_pair(
+ object(::test::generate(x, g), ::test::generate(x, g)),
+ object(::test::generate(x, g), ::test::generate(x, g)));
+ }
+
+ class hash
+ {
+ int tag_;
+
+ public:
+ hash(int t = 0) : tag_(t)
+ {
+ UNORDERED_SCOPE(hash::object())
+ {
+ UNORDERED_EPOINT("Mock hash default constructor.");
+ }
+ }
+
+ hash(hash const& x) : tag_(x.tag_)
+ {
+ UNORDERED_SCOPE(hash::hash(hash))
+ {
+ UNORDERED_EPOINT("Mock hash copy constructor.");
+ }
+ }
+
+ hash& operator=(hash const& x)
+ {
+ UNORDERED_SCOPE(hash::operator=(hash))
+ {
+ UNORDERED_EPOINT("Mock hash assign operator 1.");
+ tag_ = x.tag_;
+ UNORDERED_EPOINT("Mock hash assign operator 2.");
+ }
+ return *this;
+ }
+
+ std::size_t operator()(object const& x) const
+ {
+ UNORDERED_SCOPE(hash::operator()(object))
+ {
+ UNORDERED_EPOINT("Mock hash function.");
+ }
+
+ return hash_impl(x);
+ }
+
+ std::size_t operator()(std::pair<object, object> const& x) const
+ {
+ UNORDERED_SCOPE(hash::operator()(std::pair<object, object>))
+ {
+ UNORDERED_EPOINT("Mock hash pair function.");
+ }
+
+ return hash_impl(x.first) * 193ul + hash_impl(x.second) * 97ul + 29ul;
+ }
+
+ std::size_t hash_impl(object const& x) const
+ {
+ int result;
+ switch (tag_) {
+ case 1:
+ result = x.tag1_;
+ break;
+ case 2:
+ result = x.tag2_;
+ break;
+ default:
+ result = x.tag1_ + x.tag2_;
+ }
+ return static_cast<std::size_t>(result);
+ }
+
+ friend bool operator==(hash const& x1, hash const& x2)
+ {
+ UNORDERED_SCOPE(operator==(hash, hash))
+ {
+ UNORDERED_EPOINT("Mock hash equality function.");
+ }
+ return x1.tag_ == x2.tag_;
+ }
+
+ friend bool operator!=(hash const& x1, hash const& x2)
+ {
+ UNORDERED_SCOPE(hash::operator!=(hash, hash))
+ {
+ UNORDERED_EPOINT("Mock hash inequality function.");
+ }
+ return x1.tag_ != x2.tag_;
+ }
+ };
+
+ class less
+ {
+ int tag_;
+
+ public:
+ less(int t = 0) : tag_(t) {}
+
+ less(less const& x) : tag_(x.tag_) {}
+
+ bool operator()(object const& x1, object const& x2) const
+ {
+ return less_impl(x1, x2);
+ }
+
+ bool operator()(std::pair<object, object> const& x1,
+ std::pair<object, object> const& x2) const
+ {
+ if (less_impl(x1.first, x2.first)) {
+ return true;
+ }
+ if (!less_impl(x1.first, x2.first)) {
+ return false;
+ }
+ return less_impl(x1.second, x2.second);
+ }
+
+ bool less_impl(object const& x1, object const& x2) const
+ {
+ switch (tag_) {
+ case 1:
+ return x1.tag1_ < x2.tag1_;
+ case 2:
+ return x1.tag2_ < x2.tag2_;
+ default:
+ return x1 < x2;
+ }
+ }
+
+ friend bool operator==(less const& x1, less const& x2)
+ {
+ return x1.tag_ == x2.tag_;
+ }
+
+ friend bool operator!=(less const& x1, less const& x2)
+ {
+ return x1.tag_ != x2.tag_;
+ }
+ };
+
+ class equal_to
+ {
+ int tag_;
+
+ public:
+ equal_to(int t = 0) : tag_(t)
+ {
+ UNORDERED_SCOPE(equal_to::equal_to())
+ {
+ UNORDERED_EPOINT("Mock equal_to default constructor.");
+ }
+ }
+
+ equal_to(equal_to const& x) : tag_(x.tag_)
+ {
+ UNORDERED_SCOPE(equal_to::equal_to(equal_to))
+ {
+ UNORDERED_EPOINT("Mock equal_to copy constructor.");
+ }
+ }
+
+ equal_to& operator=(equal_to const& x)
+ {
+ UNORDERED_SCOPE(equal_to::operator=(equal_to))
+ {
+ UNORDERED_EPOINT("Mock equal_to assign operator 1.");
+ tag_ = x.tag_;
+ UNORDERED_EPOINT("Mock equal_to assign operator 2.");
+ }
+ return *this;
+ }
+
+ bool operator()(object const& x1, object const& x2) const
+ {
+ UNORDERED_SCOPE(equal_to::operator()(object, object))
+ {
+ UNORDERED_EPOINT("Mock equal_to function.");
+ }
+
+ return equal_impl(x1, x2);
+ }
+
+ bool operator()(std::pair<object, object> const& x1,
+ std::pair<object, object> const& x2) const
+ {
+ UNORDERED_SCOPE(equal_to::operator()(
+ std::pair<object, object>, std::pair<object, object>))
+ {
+ UNORDERED_EPOINT("Mock equal_to function.");
+ }
+
+ return equal_impl(x1.first, x2.first) &&
+ equal_impl(x1.second, x2.second);
+ }
+
+ bool equal_impl(object const& x1, object const& x2) const
+ {
+ switch (tag_) {
+ case 1:
+ return x1.tag1_ == x2.tag1_;
+ case 2:
+ return x1.tag2_ == x2.tag2_;
+ default:
+ return x1 == x2;
+ }
+ }
+
+ friend bool operator==(equal_to const& x1, equal_to const& x2)
+ {
+ UNORDERED_SCOPE(operator==(equal_to, equal_to))
+ {
+ UNORDERED_EPOINT("Mock equal_to equality function.");
+ }
+ return x1.tag_ == x2.tag_;
+ }
+
+ friend bool operator!=(equal_to const& x1, equal_to const& x2)
+ {
+ UNORDERED_SCOPE(operator!=(equal_to, equal_to))
+ {
+ UNORDERED_EPOINT("Mock equal_to inequality function.");
+ }
+ return x1.tag_ != x2.tag_;
+ }
+
+ friend less create_compare(equal_to x) { return less(x.tag_); }
+ };
+
+ template <class T> class allocator
+ {
+ public:
+ int tag_;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T const* const_pointer;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef T value_type;
+
+ template <class U> struct rebind
+ {
+ typedef allocator<U> other;
+ };
+
+ explicit allocator(int t = 0) : tag_(t)
+ {
+ UNORDERED_SCOPE(allocator::allocator())
+ {
+ UNORDERED_EPOINT("Mock allocator default constructor.");
+ }
+ test::detail::tracker.allocator_ref();
+ }
+
+ template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_)
+ {
+ test::detail::tracker.allocator_ref();
+ }
+
+ allocator(allocator const& x) : tag_(x.tag_)
+ {
+ test::detail::tracker.allocator_ref();
+ }
+
+ ~allocator() { test::detail::tracker.allocator_unref(); }
+
+ allocator& operator=(allocator const& x)
+ {
+ tag_ = x.tag_;
+ return *this;
+ }
+
+ // If address throws, then it can't be used in erase or the
+ // destructor, which is very limiting. I need to check up on
+ // this.
+
+ pointer address(reference r)
+ {
+ // UNORDERED_SCOPE(allocator::address(reference)) {
+ // UNORDERED_EPOINT("Mock allocator address function.");
+ //}
+ return pointer(&r);
+ }
+
+ const_pointer address(const_reference r)
+ {
+ // UNORDERED_SCOPE(allocator::address(const_reference)) {
+ // UNORDERED_EPOINT("Mock allocator const address function.");
+ //}
+ return const_pointer(&r);
+ }
+
+ pointer allocate(size_type n)
+ {
+ T* ptr = 0;
+ UNORDERED_SCOPE(allocator::allocate(size_type))
+ {
+ UNORDERED_EPOINT("Mock allocator allocate function.");
+
+ using namespace std;
+ ptr = (T*)malloc(n * sizeof(T));
+ if (!ptr)
+ throw std::bad_alloc();
+ }
+ test::detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return pointer(ptr);
+
+ // return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
+ }
+
+ pointer allocate(size_type n, void const*)
+ {
+ T* ptr = 0;
+ UNORDERED_SCOPE(allocator::allocate(size_type, const_pointer))
+ {
+ UNORDERED_EPOINT("Mock allocator allocate function.");
+
+ using namespace std;
+ ptr = (T*)malloc(n * sizeof(T));
+ if (!ptr)
+ throw std::bad_alloc();
+ }
+ test::detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return pointer(ptr);
+
+ // return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
+ }
+
+ void deallocate(pointer p, size_type n)
+ {
+ //::operator delete((void*) p);
+ if (p) {
+ test::detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_);
+ using namespace std;
+ free(p);
+ }
+ }
+
+ void construct(pointer p, T const& t)
+ {
+ UNORDERED_SCOPE(allocator::construct(T*, T))
+ {
+ UNORDERED_EPOINT("Mock allocator construct function.");
+ new (p) T(t);
+ }
+ test::detail::tracker.track_construct((void*)p, sizeof(T), tag_);
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
+ {
+ UNORDERED_SCOPE(allocator::construct(pointer, BOOST_FWD_REF(Args)...))
+ {
+ UNORDERED_EPOINT("Mock allocator construct function.");
+ new (p) T(boost::forward<Args>(args)...);
+ }
+ test::detail::tracker.track_construct((void*)p, sizeof(T), tag_);
+ }
+#endif
+
+ void destroy(T* p)
+ {
+ test::detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
+ p->~T();
+ }
+
+ size_type max_size() const
+ {
+ UNORDERED_SCOPE(allocator::construct(pointer, T))
+ {
+ UNORDERED_EPOINT("Mock allocator max_size function.");
+ }
+ return (std::numeric_limits<std::size_t>::max)();
+ }
+
+ typedef true_type propagate_on_container_copy_assignment;
+ typedef true_type propagate_on_container_move_assignment;
+ typedef true_type propagate_on_container_swap;
+ };
+
+ template <class T> void swap(allocator<T>& x, allocator<T>& y)
+ {
+ std::swap(x.tag_, y.tag_);
+ }
+
+ // It's pretty much impossible to write a compliant swap when these
+ // two can throw. So they don't.
+
+ template <class T>
+ inline bool operator==(allocator<T> const& x, allocator<T> const& y)
+ {
+ // UNORDERED_SCOPE(operator==(allocator, allocator)) {
+ // UNORDERED_EPOINT("Mock allocator equality operator.");
+ //}
+ return x.tag_ == y.tag_;
+ }
+
+ template <class T>
+ inline bool operator!=(allocator<T> const& x, allocator<T> const& y)
+ {
+ // UNORDERED_SCOPE(operator!=(allocator, allocator)) {
+ // UNORDERED_EPOINT("Mock allocator inequality operator.");
+ //}
+ return x.tag_ != y.tag_;
+ }
+
+ template <class T> class allocator2
+ {
+ public:
+ int tag_;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T const* const_pointer;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef T value_type;
+
+ template <class U> struct rebind
+ {
+ typedef allocator2<U> other;
+ };
+
+ explicit allocator2(int t = 0) : tag_(t)
+ {
+ UNORDERED_SCOPE(allocator2::allocator2())
+ {
+ UNORDERED_EPOINT("Mock allocator2 default constructor.");
+ }
+ test::detail::tracker.allocator_ref();
+ }
+
+ allocator2(allocator<T> const& x) : tag_(x.tag_)
+ {
+ test::detail::tracker.allocator_ref();
+ }
+
+ template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
+ {
+ test::detail::tracker.allocator_ref();
+ }
+
+ allocator2(allocator2 const& x) : tag_(x.tag_)
+ {
+ test::detail::tracker.allocator_ref();
+ }
+
+ ~allocator2() { test::detail::tracker.allocator_unref(); }
+
+ allocator2& operator=(allocator2 const&) { return *this; }
+
+ // If address throws, then it can't be used in erase or the
+ // destructor, which is very limiting. I need to check up on
+ // this.
+
+ pointer address(reference r)
+ {
+ // UNORDERED_SCOPE(allocator2::address(reference)) {
+ // UNORDERED_EPOINT("Mock allocator2 address function.");
+ //}
+ return pointer(&r);
+ }
+
+ const_pointer address(const_reference r)
+ {
+ // UNORDERED_SCOPE(allocator2::address(const_reference)) {
+ // UNORDERED_EPOINT("Mock allocator2 const address function.");
+ //}
+ return const_pointer(&r);
+ }
+
+ pointer allocate(size_type n)
+ {
+ T* ptr = 0;
+ UNORDERED_SCOPE(allocator2::allocate(size_type))
+ {
+ UNORDERED_EPOINT("Mock allocator2 allocate function.");
+
+ using namespace std;
+ ptr = (T*)malloc(n * sizeof(T));
+ if (!ptr)
+ throw std::bad_alloc();
+ }
+ test::detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return pointer(ptr);
+
+ // return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
+ }
+
+ pointer allocate(size_type n, void const*)
+ {
+ T* ptr = 0;
+ UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer))
+ {
+ UNORDERED_EPOINT("Mock allocator2 allocate function.");
+
+ using namespace std;
+ ptr = (T*)malloc(n * sizeof(T));
+ if (!ptr)
+ throw std::bad_alloc();
+ }
+ test::detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return pointer(ptr);
+
+ // return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
+ }
+
+ void deallocate(pointer p, size_type n)
+ {
+ //::operator delete((void*) p);
+ if (p) {
+ test::detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_);
+ using namespace std;
+ free(p);
+ }
+ }
+
+ void construct(pointer p, T const& t)
+ {
+ UNORDERED_SCOPE(allocator2::construct(T*, T))
+ {
+ UNORDERED_EPOINT("Mock allocator2 construct function.");
+ new (p) T(t);
+ }
+ test::detail::tracker.track_construct((void*)p, sizeof(T), tag_);
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
+ {
+ UNORDERED_SCOPE(allocator2::construct(pointer, BOOST_FWD_REF(Args)...))
+ {
+ UNORDERED_EPOINT("Mock allocator2 construct function.");
+ new (p) T(boost::forward<Args>(args)...);
+ }
+ test::detail::tracker.track_construct((void*)p, sizeof(T), tag_);
+ }
+#endif
+
+ void destroy(T* p)
+ {
+ test::detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
+ p->~T();
+ }
+
+ size_type max_size() const
+ {
+ UNORDERED_SCOPE(allocator2::construct(pointer, T))
+ {
+ UNORDERED_EPOINT("Mock allocator2 max_size function.");
+ }
+ return (std::numeric_limits<std::size_t>::max)();
+ }
+
+ typedef false_type propagate_on_container_copy_assignment;
+ typedef false_type propagate_on_container_move_assignment;
+ typedef false_type propagate_on_container_swap;
+ };
+
+ template <class T> void swap(allocator2<T>& x, allocator2<T>& y)
+ {
+ std::swap(x.tag_, y.tag_);
+ }
+
+ // It's pretty much impossible to write a compliant swap when these
+ // two can throw. So they don't.
+
+ template <class T>
+ inline bool operator==(allocator2<T> const& x, allocator2<T> const& y)
+ {
+ // UNORDERED_SCOPE(operator==(allocator2, allocator2)) {
+ // UNORDERED_EPOINT("Mock allocator2 equality operator.");
+ //}
+ return x.tag_ == y.tag_;
+ }
+
+ template <class T>
+ inline bool operator!=(allocator2<T> const& x, allocator2<T> const& y)
+ {
+ // UNORDERED_SCOPE(operator!=(allocator2, allocator2)) {
+ // UNORDERED_EPOINT("Mock allocator2 inequality operator.");
+ //}
+ return x.tag_ != y.tag_;
+ }
+ }
+}
+
+namespace test {
+ template <typename X> struct equals_to_compare;
+ template <> struct equals_to_compare<test::exception::equal_to>
+ {
+ typedef test::exception::less type;
+ };
+}
+
+// Workaround for ADL deficient compilers
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+namespace test {
+ test::exception::object generate(
+ test::exception::object const* x, random_generator g)
+ {
+ return test::exception::generate(x, g);
+ }
+
+ std::pair<test::exception::object, test::exception::object> generate(
+ std::pair<test::exception::object, test::exception::object> const* x,
+ random_generator g)
+ {
+ return test::exception::generate(x, g);
+ }
+}
+#endif
+
+#endif
diff --git a/src/boost/libs/unordered/test/objects/fwd.hpp b/src/boost/libs/unordered/test/objects/fwd.hpp
new file mode 100644
index 000000000..802b95af4
--- /dev/null
+++ b/src/boost/libs/unordered/test/objects/fwd.hpp
@@ -0,0 +1,17 @@
+
+// Copyright 2006-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_OBJECTS_FWD_HEADER)
+#define BOOST_UNORDERED_TEST_OBJECTS_FWD_HEADER
+
+namespace test {
+ class object;
+ class hash;
+ class less;
+ class equal_to;
+ template <class T> class allocator;
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/objects/minimal.hpp b/src/boost/libs/unordered/test/objects/minimal.hpp
new file mode 100644
index 000000000..b89e0af82
--- /dev/null
+++ b/src/boost/libs/unordered/test/objects/minimal.hpp
@@ -0,0 +1,627 @@
+
+// Copyright 2006-2009 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)
+
+// Define some minimal classes which provide the bare minimum concepts to
+// test that the containers don't rely on something that they shouldn't.
+// They are not intended to be good examples of how to implement the concepts.
+
+#if !defined(BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER)
+#define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER
+
+#include <boost/move/move.hpp>
+#include <cstddef>
+#include <utility>
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
+#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
+#else
+#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
+#endif
+
+namespace test {
+ namespace minimal {
+ class destructible;
+ class copy_constructible;
+ class copy_constructible_equality_comparable;
+ class default_assignable;
+ class assignable;
+
+ struct ampersand_operator_used
+ {
+ ampersand_operator_used() { BOOST_TEST(false); }
+ };
+
+ template <class T> class hash;
+ template <class T> class equal_to;
+ template <class T> class ptr;
+ template <class T> class const_ptr;
+ template <class T> class allocator;
+ template <class T> class cxx11_allocator;
+
+ struct constructor_param
+ {
+ operator int() const { return 0; }
+ };
+
+ class destructible
+ {
+ public:
+ destructible(constructor_param const&) {}
+ ~destructible() {}
+ void dummy_member() const {}
+
+ private:
+ destructible(destructible const&);
+ destructible& operator=(destructible const&);
+ };
+
+ class copy_constructible
+ {
+ public:
+ copy_constructible(constructor_param const&) {}
+ copy_constructible(copy_constructible const&) {}
+ ~copy_constructible() {}
+ void dummy_member() const {}
+
+ private:
+ copy_constructible& operator=(copy_constructible const&);
+ copy_constructible() {}
+ };
+
+ class copy_constructible_equality_comparable
+ {
+ public:
+ copy_constructible_equality_comparable(constructor_param const&) {}
+
+ copy_constructible_equality_comparable(
+ copy_constructible_equality_comparable const&)
+ {
+ }
+
+ ~copy_constructible_equality_comparable() {}
+
+ void dummy_member() const {}
+
+ private:
+ copy_constructible_equality_comparable& operator=(
+ copy_constructible_equality_comparable const&);
+ copy_constructible_equality_comparable() {}
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ bool operator==(copy_constructible_equality_comparable,
+ copy_constructible_equality_comparable)
+ {
+ return true;
+ }
+
+ bool operator!=(copy_constructible_equality_comparable,
+ copy_constructible_equality_comparable)
+ {
+ return false;
+ }
+
+ class default_assignable
+ {
+ public:
+ default_assignable(constructor_param const&) {}
+
+ default_assignable() {}
+
+ default_assignable(default_assignable const&) {}
+
+ default_assignable& operator=(default_assignable const&) { return *this; }
+
+ ~default_assignable() {}
+
+ void dummy_member() const {}
+
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ class assignable
+ {
+ public:
+ assignable(constructor_param const&) {}
+ assignable(assignable const&) {}
+ assignable& operator=(assignable const&) { return *this; }
+ ~assignable() {}
+ void dummy_member() const {}
+
+ private:
+ assignable() {}
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ struct movable_init
+ {
+ };
+
+ class movable1
+ {
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(movable1)
+
+ public:
+ movable1(constructor_param const&) {}
+ movable1() {}
+ explicit movable1(movable_init) {}
+ movable1(BOOST_RV_REF(movable1)) {}
+ movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
+ ~movable1() {}
+ void dummy_member() const {}
+ };
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ class movable2
+ {
+ public:
+ movable2(constructor_param const&) {}
+ explicit movable2(movable_init) {}
+ movable2(movable2&&) {}
+ ~movable2() {}
+ movable2& operator=(movable2&&) { return *this; }
+ void dummy_member() const {}
+
+ private:
+ movable2() {}
+ movable2(movable2 const&);
+ movable2& operator=(movable2 const&);
+ };
+#else
+ typedef movable1 movable2;
+#endif
+
+ template <class T> class hash
+ {
+ public:
+ hash(constructor_param const&) {}
+ hash() {}
+ hash(hash const&) {}
+ hash& operator=(hash const&) { return *this; }
+ ~hash() {}
+
+ std::size_t operator()(T const&) const { return 0; }
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ template <class T> class equal_to
+ {
+ public:
+ equal_to(constructor_param const&) {}
+ equal_to() {}
+ equal_to(equal_to const&) {}
+ equal_to& operator=(equal_to const&) { return *this; }
+ ~equal_to() {}
+
+ bool operator()(T const&, T const&) const { return true; }
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ template <class T> class ptr;
+ template <class T> class const_ptr;
+
+ struct void_ptr
+ {
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename T> friend class ptr;
+
+ private:
+#endif
+
+ void* ptr_;
+
+ public:
+ void_ptr() : ptr_(0) {}
+
+ template <typename T> explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
+
+ // I'm not using the safe bool idiom because the containers should be
+ // able to cope with bool conversions.
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
+ };
+
+ class void_const_ptr
+ {
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename T> friend class const_ptr;
+
+ private:
+#endif
+
+ void* ptr_;
+
+ public:
+ void_const_ptr() : ptr_(0) {}
+
+ template <typename T>
+ explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_)
+ {
+ }
+
+ // I'm not using the safe bool idiom because the containers should be
+ // able to cope with bool conversions.
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
+ };
+
+ template <class T> class ptr
+ {
+ friend class allocator<T>;
+ friend class const_ptr<T>;
+ friend struct void_ptr;
+
+ T* ptr_;
+
+ ptr(T* x) : ptr_(x) {}
+
+ public:
+ ptr() : ptr_(0) {}
+ explicit ptr(void_ptr const& x) : ptr_((T*)x.ptr_) {}
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+ ptr& operator++()
+ {
+ ++ptr_;
+ return *this;
+ }
+ ptr operator++(int)
+ {
+ ptr tmp(*this);
+ ++ptr_;
+ return tmp;
+ }
+ ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
+ friend ptr operator+(std::ptrdiff_t s, ptr p)
+ {
+ return ptr<T>(s + p.ptr_);
+ }
+ T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
+ bool operator!() const { return !ptr_; }
+
+ // I'm not using the safe bool idiom because the containers should be
+ // able to cope with bool conversions.
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; }
+ bool operator<(ptr const& x) const { return ptr_ < x.ptr_; }
+ bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
+ bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
+ bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ template <class T> class const_ptr
+ {
+ friend class allocator<T>;
+ friend struct const_void_ptr;
+
+ T const* ptr_;
+
+ const_ptr(T const* ptr) : ptr_(ptr) {}
+
+ public:
+ const_ptr() : ptr_(0) {}
+ const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
+ explicit const_ptr(void_const_ptr const& x) : ptr_((T const*)x.ptr_) {}
+
+ T const& operator*() const { return *ptr_; }
+ T const* operator->() const { return ptr_; }
+ const_ptr& operator++()
+ {
+ ++ptr_;
+ return *this;
+ }
+ const_ptr operator++(int)
+ {
+ const_ptr tmp(*this);
+ ++ptr_;
+ return tmp;
+ }
+ const_ptr operator+(std::ptrdiff_t s) const
+ {
+ return const_ptr(ptr_ + s);
+ }
+ friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
+ {
+ return ptr<T>(s + p.ptr_);
+ }
+ T const& operator[](int s) const { return ptr_[s]; }
+ bool operator!() const { return !ptr_; }
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
+ bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
+ bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
+ bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
+ bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ template <class T> class allocator
+ {
+ public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef void_ptr void_pointer;
+ typedef void_const_ptr const_void_pointer;
+ typedef ptr<T> pointer;
+ typedef const_ptr<T> const_pointer;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef T value_type;
+
+ template <class U> struct rebind
+ {
+ typedef allocator<U> other;
+ };
+
+ allocator() {}
+ template <class Y> allocator(allocator<Y> const&) {}
+ allocator(allocator const&) {}
+ ~allocator() {}
+
+ pointer address(reference r) { return pointer(&r); }
+ const_pointer address(const_reference r) { return const_pointer(&r); }
+
+ pointer allocate(size_type n)
+ {
+ return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
+ }
+
+ template <class Y> pointer allocate(size_type n, const_ptr<Y>)
+ {
+ return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
+ }
+
+ void deallocate(pointer p, size_type)
+ {
+ ::operator delete((void*)p.ptr_);
+ }
+
+ void construct(T* p, T const& t) { new ((void*)p) T(t); }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
+ {
+ new ((void*)p) T(boost::forward<Args>(args)...);
+ }
+#endif
+
+ void destroy(T* p) { p->~T(); }
+
+ size_type max_size() const { return 1000; }
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \
+ BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ public:
+ allocator& operator=(allocator const&) { return *this; }
+#else
+ private:
+ allocator& operator=(allocator const&);
+#endif
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ template <class T> class allocator<T const>
+ {
+ public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef void_ptr void_pointer;
+ typedef void_const_ptr const_void_pointer;
+ // Maybe these two should be const_ptr<T>
+ typedef ptr<T const> pointer;
+ typedef const_ptr<T const> const_pointer;
+ typedef T const& reference;
+ typedef T const& const_reference;
+ typedef T const value_type;
+
+ template <class U> struct rebind
+ {
+ typedef allocator<U> other;
+ };
+
+ allocator() {}
+ template <class Y> allocator(allocator<Y> const&) {}
+ allocator(allocator const&) {}
+ ~allocator() {}
+
+ const_pointer address(const_reference r) { return const_pointer(&r); }
+
+ pointer allocate(size_type n)
+ {
+ return pointer(static_cast<T const*>(::operator new(n * sizeof(T))));
+ }
+
+ template <class Y> pointer allocate(size_type n, const_ptr<Y>)
+ {
+ return pointer(static_cast<T const*>(::operator new(n * sizeof(T))));
+ }
+
+ void deallocate(pointer p, size_type)
+ {
+ ::operator delete((void*)p.ptr_);
+ }
+
+ void construct(T const* p, T const& t) { new ((void*)p) T(t); }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class... Args>
+ void construct(T const* p, BOOST_FWD_REF(Args)... args)
+ {
+ new ((void*)p) T(boost::forward<Args>(args)...);
+ }
+#endif
+
+ void destroy(T const* p) { p->~T(); }
+
+ size_type max_size() const { return 1000; }
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || \
+ BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ public:
+ allocator& operator=(allocator const&) { return *this; }
+#else
+ private:
+ allocator& operator=(allocator const&);
+#endif
+#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
+ ampersand_operator_used operator&() const
+ {
+ return ampersand_operator_used();
+ }
+#endif
+ };
+
+ template <class T>
+ inline bool operator==(allocator<T> const&, allocator<T> const&)
+ {
+ return true;
+ }
+
+ template <class T>
+ inline bool operator!=(allocator<T> const&, allocator<T> const&)
+ {
+ return false;
+ }
+
+ template <class T> void swap(allocator<T>&, allocator<T>&) {}
+
+ // C++11 allocator
+ //
+ // Not a fully minimal C++11 allocator, just what I support. Hopefully will
+ // cut down further in the future.
+
+ template <class T> class cxx11_allocator
+ {
+ public:
+ typedef T value_type;
+ // template <class U> struct rebind { typedef cxx11_allocator<U> other; };
+
+ cxx11_allocator() {}
+ template <class Y> cxx11_allocator(cxx11_allocator<Y> const&) {}
+ cxx11_allocator(cxx11_allocator const&) {}
+ ~cxx11_allocator() {}
+
+ T* address(T& r) { return &r; }
+ T const* address(T const& r) { return &r; }
+
+ T* allocate(std::size_t n)
+ {
+ return static_cast<T*>(::operator new(n * sizeof(T)));
+ }
+
+ template <class Y> T* allocate(std::size_t n, const_ptr<Y>)
+ {
+ return static_cast<T*>(::operator new(n * sizeof(T)));
+ }
+
+ void deallocate(T* p, std::size_t) { ::operator delete((void*)p); }
+
+ void construct(T* p, T const& t) { new ((void*)p) T(t); }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
+ {
+ new ((void*)p) T(boost::forward<Args>(args)...);
+ }
+#endif
+
+ void destroy(T* p) { p->~T(); }
+
+ std::size_t max_size() const { return 1000u; }
+ };
+
+ template <class T>
+ inline bool operator==(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
+ {
+ return true;
+ }
+
+ template <class T>
+ inline bool operator!=(cxx11_allocator<T> const&, cxx11_allocator<T> const&)
+ {
+ return false;
+ }
+
+ template <class T> void swap(cxx11_allocator<T>&, cxx11_allocator<T>&) {}
+ }
+}
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+namespace boost {
+#else
+namespace test {
+ namespace minimal {
+#endif
+ std::size_t hash_value(test::minimal::copy_constructible_equality_comparable)
+ {
+ return 1;
+ }
+#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+}
+}
+#else
+ }
+#endif
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/src/boost/libs/unordered/test/objects/test.hpp b/src/boost/libs/unordered/test/objects/test.hpp
new file mode 100644
index 000000000..7ce21fa95
--- /dev/null
+++ b/src/boost/libs/unordered/test/objects/test.hpp
@@ -0,0 +1,700 @@
+
+// Copyright 2006-2009 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)
+
+#if !defined(BOOST_UNORDERED_TEST_OBJECTS_HEADER)
+#define BOOST_UNORDERED_TEST_OBJECTS_HEADER
+
+#include "../helpers/count.hpp"
+#include "../helpers/fwd.hpp"
+#include "../helpers/memory.hpp"
+#include <boost/config.hpp>
+#include <boost/limits.hpp>
+#include <cstddef>
+
+namespace test {
+ // Note that the default hash function will work for any equal_to (but not
+ // very well).
+ class object;
+ class movable;
+ class implicitly_convertible;
+ class hash;
+ class less;
+ class equal_to;
+ template <class T> class allocator1;
+ template <class T> class allocator2;
+ object generate(object const*, random_generator);
+ movable generate(movable const*, random_generator);
+ implicitly_convertible generate(
+ implicitly_convertible const*, random_generator);
+
+ inline void ignore_variable(void const*) {}
+
+ class object : private counted_object
+ {
+ friend class hash;
+ friend class equal_to;
+ friend class less;
+ int tag1_, tag2_;
+
+ public:
+ explicit object(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
+
+ ~object()
+ {
+ tag1_ = -1;
+ tag2_ = -1;
+ }
+
+ friend bool operator==(object const& x1, object const& x2)
+ {
+ return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
+ }
+
+ friend bool operator!=(object const& x1, object const& x2)
+ {
+ return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
+ }
+
+ friend bool operator<(object const& x1, object const& x2)
+ {
+ return x1.tag1_ < x2.tag1_ ||
+ (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
+ }
+
+ friend object generate(object const*, random_generator g)
+ {
+ int* x = 0;
+ return object(generate(x, g), generate(x, g));
+ }
+
+ friend std::ostream& operator<<(std::ostream& out, object const& o)
+ {
+ return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
+ }
+ };
+
+ class movable : private counted_object
+ {
+ friend class hash;
+ friend class equal_to;
+ friend class less;
+ int tag1_, tag2_;
+
+ BOOST_COPYABLE_AND_MOVABLE(movable)
+ public:
+ explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
+
+ movable(movable const& x)
+ : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
+ {
+ BOOST_TEST(x.tag1_ != -1);
+ }
+
+ movable(BOOST_RV_REF(movable) x)
+ : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
+ {
+ BOOST_TEST(x.tag1_ != -1);
+ x.tag1_ = -1;
+ x.tag2_ = -1;
+ }
+
+ movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment
+ {
+ BOOST_TEST(x.tag1_ != -1);
+ tag1_ = x.tag1_;
+ tag2_ = x.tag2_;
+ return *this;
+ }
+
+ movable& operator=(BOOST_RV_REF(movable) x) // Move assignment
+ {
+ BOOST_TEST(x.tag1_ != -1);
+ tag1_ = x.tag1_;
+ tag2_ = x.tag2_;
+ x.tag1_ = -1;
+ x.tag2_ = -1;
+ return *this;
+ }
+
+ ~movable()
+ {
+ tag1_ = -1;
+ tag2_ = -1;
+ }
+
+ friend bool operator==(movable const& x1, movable const& x2)
+ {
+ BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
+ return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
+ }
+
+ friend bool operator!=(movable const& x1, movable const& x2)
+ {
+ BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
+ return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
+ }
+
+ friend bool operator<(movable const& x1, movable const& x2)
+ {
+ BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
+ return x1.tag1_ < x2.tag1_ ||
+ (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
+ }
+
+ friend movable generate(movable const*, random_generator g)
+ {
+ int* x = 0;
+ return movable(generate(x, g), generate(x, g));
+ }
+
+ friend std::ostream& operator<<(std::ostream& out, movable const& o)
+ {
+ return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
+ }
+ };
+
+ class implicitly_convertible : private counted_object
+ {
+ int tag1_, tag2_;
+
+ public:
+ explicit implicitly_convertible(int t1 = 0, int t2 = 0)
+ : tag1_(t1), tag2_(t2)
+ {
+ }
+
+ operator object() const { return object(tag1_, tag2_); }
+
+ operator movable() const { return movable(tag1_, tag2_); }
+
+ friend implicitly_convertible generate(
+ implicitly_convertible const*, random_generator g)
+ {
+ int* x = 0;
+ return implicitly_convertible(generate(x, g), generate(x, g));
+ }
+
+ friend std::ostream& operator<<(
+ std::ostream& out, implicitly_convertible const& o)
+ {
+ return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
+ }
+ };
+
+ // Note: This is a deliberately bad hash function.
+ class hash
+ {
+ int type_;
+
+ public:
+ hash() : type_(0) {}
+
+ explicit hash(int t) : type_(t) {}
+
+ std::size_t operator()(object const& x) const
+ {
+ int result;
+ switch (type_) {
+ case 1:
+ result = x.tag1_;
+ break;
+ case 2:
+ result = x.tag2_;
+ break;
+ default:
+ result = x.tag1_ + x.tag2_;
+ }
+ return static_cast<std::size_t>(result);
+ }
+
+ std::size_t operator()(movable const& x) const
+ {
+ int result;
+ switch (type_) {
+ case 1:
+ result = x.tag1_;
+ break;
+ case 2:
+ result = x.tag2_;
+ break;
+ default:
+ result = x.tag1_ + x.tag2_;
+ }
+ return static_cast<std::size_t>(result);
+ }
+
+ std::size_t operator()(int x) const
+ {
+ int result;
+ switch (type_) {
+ case 1:
+ result = x;
+ break;
+ case 2:
+ result = x * 7;
+ break;
+ default:
+ result = x * 256;
+ }
+ return static_cast<std::size_t>(result);
+ }
+
+ friend bool operator==(hash const& x1, hash const& x2)
+ {
+ return x1.type_ == x2.type_;
+ }
+
+ friend bool operator!=(hash const& x1, hash const& x2)
+ {
+ return x1.type_ != x2.type_;
+ }
+ };
+
+ std::size_t hash_value(test::object const& x) { return hash()(x); }
+
+ std::size_t hash_value(test::movable const& x) { return hash()(x); }
+
+ class less
+ {
+ int type_;
+
+ public:
+ explicit less(int t = 0) : type_(t) {}
+
+ bool operator()(object const& x1, object const& x2) const
+ {
+ switch (type_) {
+ case 1:
+ return x1.tag1_ < x2.tag1_;
+ case 2:
+ return x1.tag2_ < x2.tag2_;
+ default:
+ return x1 < x2;
+ }
+ }
+
+ bool operator()(movable const& x1, movable const& x2) const
+ {
+ switch (type_) {
+ case 1:
+ return x1.tag1_ < x2.tag1_;
+ case 2:
+ return x1.tag2_ < x2.tag2_;
+ default:
+ return x1 < x2;
+ }
+ }
+
+ std::size_t operator()(int x1, int x2) const { return x1 < x2; }
+
+ friend bool operator==(less const& x1, less const& x2)
+ {
+ return x1.type_ == x2.type_;
+ }
+ };
+
+ class equal_to
+ {
+ int type_;
+
+ public:
+ equal_to() : type_(0) {}
+
+ explicit equal_to(int t) : type_(t) {}
+
+ bool operator()(object const& x1, object const& x2) const
+ {
+ switch (type_) {
+ case 1:
+ return x1.tag1_ == x2.tag1_;
+ case 2:
+ return x1.tag2_ == x2.tag2_;
+ default:
+ return x1 == x2;
+ }
+ }
+
+ bool operator()(movable const& x1, movable const& x2) const
+ {
+ switch (type_) {
+ case 1:
+ return x1.tag1_ == x2.tag1_;
+ case 2:
+ return x1.tag2_ == x2.tag2_;
+ default:
+ return x1 == x2;
+ }
+ }
+
+ std::size_t operator()(int x1, int x2) const { return x1 == x2; }
+
+ friend bool operator==(equal_to const& x1, equal_to const& x2)
+ {
+ return x1.type_ == x2.type_;
+ }
+
+ friend bool operator!=(equal_to const& x1, equal_to const& x2)
+ {
+ return x1.type_ != x2.type_;
+ }
+
+ friend less create_compare(equal_to x) { return less(x.type_); }
+ };
+
+ // allocator1 only has the old fashioned 'construct' method and has
+ // a few less typedefs. allocator2 uses a custom pointer class.
+
+ template <class T> class allocator1
+ {
+ public:
+ int tag_;
+
+ typedef T value_type;
+
+ template <class U> struct rebind
+ {
+ typedef allocator1<U> other;
+ };
+
+ allocator1() : tag_(0) { detail::tracker.allocator_ref(); }
+
+ explicit allocator1(int t) : tag_(t) { detail::tracker.allocator_ref(); }
+
+ template <class Y> allocator1(allocator1<Y> const& x) : tag_(x.tag_)
+ {
+ detail::tracker.allocator_ref();
+ }
+
+ allocator1(allocator1 const& x) : tag_(x.tag_)
+ {
+ detail::tracker.allocator_ref();
+ }
+
+ ~allocator1() { detail::tracker.allocator_unref(); }
+
+ T* allocate(std::size_t n)
+ {
+ T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
+ detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return ptr;
+ }
+
+ T* allocate(std::size_t n, void const*)
+ {
+ T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
+ detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return ptr;
+ }
+
+ void deallocate(T* p, std::size_t n)
+ {
+ detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_);
+ ::operator delete((void*)p);
+ }
+
+#if BOOST_UNORDERED_CXX11_CONSTRUCTION
+ template <typename U, typename... Args> void construct(U* p, Args&&... args)
+ {
+ detail::tracker.track_construct((void*)p, sizeof(U), tag_);
+ new (p) U(boost::forward<Args>(args)...);
+ }
+
+ template <typename U> void destroy(U* p)
+ {
+ detail::tracker.track_destroy((void*)p, sizeof(U), tag_);
+ p->~U();
+
+ // Work around MSVC buggy unused parameter warning.
+ ignore_variable(&p);
+ }
+#else
+ private:
+ // I'm going to claim in the documentation that construct/destroy
+ // is never used when C++11 support isn't available, so might as
+ // well check that in the text.
+ // TODO: Or maybe just disallow them for values?
+ template <typename U> void construct(U* p);
+ template <typename U, typename A0> void construct(U* p, A0 const&);
+ template <typename U, typename A0, typename A1>
+ void construct(U* p, A0 const&, A1 const&);
+ template <typename U, typename A0, typename A1, typename A2>
+ void construct(U* p, A0 const&, A1 const&, A2 const&);
+ template <typename U> void destroy(U* p);
+
+ public:
+#endif
+
+ bool operator==(allocator1 const& x) const { return tag_ == x.tag_; }
+
+ bool operator!=(allocator1 const& x) const { return tag_ != x.tag_; }
+
+ enum
+ {
+ is_select_on_copy = false,
+ is_propagate_on_swap = false,
+ is_propagate_on_assign = false,
+ is_propagate_on_move = false
+ };
+ };
+
+ template <class T> class ptr;
+ template <class T> class const_ptr;
+
+ struct void_ptr
+ {
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename T> friend class ptr;
+
+ private:
+#endif
+
+ void* ptr_;
+
+ public:
+ void_ptr() : ptr_(0) {}
+
+ template <typename T> explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
+
+ // I'm not using the safe bool idiom because the containers should be
+ // able to cope with bool conversions.
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
+ };
+
+ class void_const_ptr
+ {
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename T> friend class const_ptr;
+
+ private:
+#endif
+
+ void* ptr_;
+
+ public:
+ void_const_ptr() : ptr_(0) {}
+
+ template <typename T>
+ explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_)
+ {
+ }
+
+ // I'm not using the safe bool idiom because the containers should be
+ // able to cope with bool conversions.
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
+ };
+
+ template <class T> class ptr
+ {
+ friend class allocator2<T>;
+ friend class const_ptr<T>;
+ friend struct void_ptr;
+
+ T* ptr_;
+
+ ptr(T* x) : ptr_(x) {}
+
+ public:
+ ptr() : ptr_(0) {}
+ explicit ptr(void_ptr const& x) : ptr_((T*)x.ptr_) {}
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+ ptr& operator++()
+ {
+ ++ptr_;
+ return *this;
+ }
+ ptr operator++(int)
+ {
+ ptr tmp(*this);
+ ++ptr_;
+ return tmp;
+ }
+ ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
+ friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr<T>(s + p.ptr_); }
+ T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
+ bool operator!() const { return !ptr_; }
+
+ // I'm not using the safe bool idiom because the containers should be
+ // able to cope with bool conversions.
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(ptr const& x) const { return ptr_ != x.ptr_; }
+ bool operator<(ptr const& x) const { return ptr_ < x.ptr_; }
+ bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
+ bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
+ bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
+ };
+
+ template <class T> class const_ptr
+ {
+ friend class allocator2<T>;
+ friend struct const_void_ptr;
+
+ T const* ptr_;
+
+ const_ptr(T const* ptr) : ptr_(ptr) {}
+
+ public:
+ const_ptr() : ptr_(0) {}
+ const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
+ explicit const_ptr(void_const_ptr const& x) : ptr_((T const*)x.ptr_) {}
+
+ T const& operator*() const { return *ptr_; }
+ T const* operator->() const { return ptr_; }
+ const_ptr& operator++()
+ {
+ ++ptr_;
+ return *this;
+ }
+ const_ptr operator++(int)
+ {
+ const_ptr tmp(*this);
+ ++ptr_;
+ return tmp;
+ }
+ const_ptr operator+(std::ptrdiff_t s) const { return const_ptr(ptr_ + s); }
+ friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
+ {
+ return ptr<T>(s + p.ptr_);
+ }
+ T const& operator[](int s) const { return ptr_[s]; }
+ bool operator!() const { return !ptr_; }
+ operator bool() const { return !!ptr_; }
+
+ bool operator==(const_ptr const& x) const { return ptr_ == x.ptr_; }
+ bool operator!=(const_ptr const& x) const { return ptr_ != x.ptr_; }
+ bool operator<(const_ptr const& x) const { return ptr_ < x.ptr_; }
+ bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
+ bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
+ bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
+ };
+
+ template <class T> class allocator2
+ {
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+ public:
+#else
+ template <class> friend class allocator2;
+#endif
+ int tag_;
+
+ public:
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef void_ptr void_pointer;
+ typedef void_const_ptr const_void_pointer;
+ typedef ptr<T> pointer;
+ typedef const_ptr<T> const_pointer;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef T value_type;
+
+ template <class U> struct rebind
+ {
+ typedef allocator2<U> other;
+ };
+
+ allocator2() : tag_(0) { detail::tracker.allocator_ref(); }
+
+ explicit allocator2(int t) : tag_(t) { detail::tracker.allocator_ref(); }
+
+ template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
+ {
+ detail::tracker.allocator_ref();
+ }
+
+ allocator2(allocator2 const& x) : tag_(x.tag_)
+ {
+ detail::tracker.allocator_ref();
+ }
+
+ ~allocator2() { detail::tracker.allocator_unref(); }
+
+ pointer address(reference r) { return pointer(&r); }
+
+ const_pointer address(const_reference r) { return const_pointer(&r); }
+
+ pointer allocate(size_type n)
+ {
+ pointer p(static_cast<T*>(::operator new(n * sizeof(T))));
+ detail::tracker.track_allocate((void*)p.ptr_, n, sizeof(T), tag_);
+ return p;
+ }
+
+ pointer allocate(size_type n, void const*)
+ {
+ pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
+ detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
+ return ptr;
+ }
+
+ void deallocate(pointer p, size_type n)
+ {
+ detail::tracker.track_deallocate((void*)p.ptr_, n, sizeof(T), tag_);
+ ::operator delete((void*)p.ptr_);
+ }
+
+ void construct(T* p, T const& t)
+ {
+ detail::tracker.track_construct((void*)p, sizeof(T), tag_);
+ new (p) T(t);
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
+ {
+ detail::tracker.track_construct((void*)p, sizeof(T), tag_);
+ new (p) T(boost::forward<Args>(args)...);
+ }
+#endif
+
+ void destroy(T* p)
+ {
+ detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
+ p->~T();
+ }
+
+ size_type max_size() const
+ {
+ return (std::numeric_limits<size_type>::max)();
+ }
+
+ bool operator==(allocator2 const& x) const { return tag_ == x.tag_; }
+
+ bool operator!=(allocator2 const& x) const { return tag_ != x.tag_; }
+
+ enum
+ {
+ is_select_on_copy = false,
+ is_propagate_on_swap = false,
+ is_propagate_on_assign = false,
+ is_propagate_on_move = false
+ };
+ };
+
+ template <class T>
+ bool equivalent_impl(
+ allocator1<T> const& x, allocator1<T> const& y, test::derived_type)
+ {
+ return x == y;
+ }
+
+ template <class T>
+ bool equivalent_impl(
+ allocator2<T> const& x, allocator2<T> const& y, test::derived_type)
+ {
+ return x == y;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/unordered/test/unordered/allocator_traits.cpp b/src/boost/libs/unordered/test/unordered/allocator_traits.cpp
new file mode 100644
index 000000000..476205b7b
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/allocator_traits.cpp
@@ -0,0 +1,288 @@
+
+// Copyright 2011 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 <boost/core/lightweight_test.hpp>
+#include <boost/limits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/unordered/detail/implementation.hpp>
+
+// Boilerplate
+
+#define ALLOCATOR_METHODS(name) \
+ template <typename U> struct rebind \
+ { \
+ typedef name<U> other; \
+ }; \
+ \
+ name() {} \
+ template <typename Y> name(name<Y> const&) {} \
+ T* address(T& r) { return &r; } \
+ T const* address(T const& r) { return &r; } \
+ T* allocate(std::size_t n) \
+ { \
+ return static_cast<T*>(::operator new(n * sizeof(T))); \
+ } \
+ T* allocate(std::size_t n, void const*) \
+ { \
+ return static_cast<T*>(::operator new(n * sizeof(T))); \
+ } \
+ void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } \
+ void construct(T* p, T const& t) { new (p) T(t); } \
+ void destroy(T* p) { p->~T(); } \
+ std::size_t max_size() const \
+ { \
+ return (std::numeric_limits<std::size_t>::max)(); \
+ } \
+ bool operator==(name<T> const&) const { return true; } \
+ bool operator!=(name<T> const&) const { return false; } \
+/**/
+
+#define ALLOCATOR_METHODS_TYPEDEFS(name) \
+ template <typename U> struct rebind \
+ { \
+ typedef name<U> other; \
+ }; \
+ \
+ name() {} \
+ template <typename Y> name(name<Y> const&) {} \
+ pointer address(T& r) { return &r; } \
+ const_pointer address(T const& r) { return &r; } \
+ pointer allocate(std::size_t n) \
+ { \
+ return pointer(::operator new(n * sizeof(T))); \
+ } \
+ pointer allocate(std::size_t n, void const*) \
+ { \
+ return pointer(::operator new(n * sizeof(T))); \
+ } \
+ void deallocate(pointer p, std::size_t) { ::operator delete((void*)p); } \
+ void construct(T* p, T const& t) { new (p) T(t); } \
+ void destroy(T* p) { p->~T(); } \
+ size_type max_size() const \
+ { \
+ return (std::numeric_limits<size_type>::max)(); \
+ } \
+ bool operator==(name<T> const&) { return true; } \
+ bool operator!=(name<T> const&) { return false; } \
+/**/
+
+struct yes_type
+{
+ enum
+ {
+ value = true
+ };
+};
+struct no_type
+{
+ enum
+ {
+ value = false
+ };
+};
+
+// For tracking calls...
+
+static int selected;
+void reset() { selected = 0; }
+
+template <typename Allocator> int call_select()
+{
+ typedef boost::unordered::detail::allocator_traits<Allocator> traits;
+ Allocator a;
+
+ reset();
+ BOOST_TEST(traits::select_on_container_copy_construction(a) == a);
+ return selected;
+}
+
+// Empty allocator test
+
+template <typename T> struct empty_allocator
+{
+ typedef T value_type;
+ ALLOCATOR_METHODS(empty_allocator)
+};
+
+void test_empty_allocator()
+{
+ typedef empty_allocator<int> allocator;
+ typedef boost::unordered::detail::allocator_traits<allocator> traits;
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+ BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
+ std::make_unsigned<std::ptrdiff_t>::type>::value));
+#else
+ BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
+#endif
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::const_pointer, int const*>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
+ BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
+ BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
+ BOOST_TEST(!traits::propagate_on_container_swap::value);
+ BOOST_TEST(traits::is_always_equal::value);
+ BOOST_TEST(call_select<allocator>() == 0);
+}
+
+// allocator 1
+
+template <typename T> struct allocator1
+{
+ typedef T value_type;
+ ALLOCATOR_METHODS(allocator1)
+
+ typedef yes_type propagate_on_container_copy_assignment;
+ typedef yes_type propagate_on_container_move_assignment;
+ typedef yes_type propagate_on_container_swap;
+ typedef yes_type is_always_equal;
+
+ allocator1<T> select_on_container_copy_construction() const
+ {
+ ++selected;
+ return allocator1<T>();
+ }
+};
+
+void test_allocator1()
+{
+ typedef allocator1<int> allocator;
+ typedef boost::unordered::detail::allocator_traits<allocator> traits;
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+ BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
+ std::make_unsigned<std::ptrdiff_t>::type>::value));
+#else
+ BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
+#endif
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::const_pointer, int const*>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
+ BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
+ BOOST_TEST(traits::propagate_on_container_move_assignment::value);
+ BOOST_TEST(traits::propagate_on_container_swap::value);
+ BOOST_TEST(traits::is_always_equal::value);
+ BOOST_TEST(call_select<allocator>() == 1);
+}
+
+// allocator 2
+
+template <typename Alloc> struct allocator2_base
+{
+ Alloc select_on_container_copy_construction() const
+ {
+ ++selected;
+ return Alloc();
+ }
+};
+
+template <typename T> struct allocator2 : allocator2_base<allocator2<T> >
+{
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T const* const_pointer;
+ typedef std::size_t size_type;
+
+ ALLOCATOR_METHODS(allocator2)
+
+ typedef no_type propagate_on_container_copy_assignment;
+ typedef no_type propagate_on_container_move_assignment;
+ typedef no_type propagate_on_container_swap;
+ typedef no_type is_always_equal;
+};
+
+void test_allocator2()
+{
+ typedef allocator2<int> allocator;
+ typedef boost::unordered::detail::allocator_traits<allocator> traits;
+ BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::const_pointer, int const*>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
+ BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
+ BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
+ BOOST_TEST(!traits::propagate_on_container_swap::value);
+ BOOST_TEST(!traits::is_always_equal::value);
+ BOOST_TEST(call_select<allocator>() == 1);
+}
+
+// allocator 3
+
+template <typename T> struct ptr
+{
+ T* value_;
+
+ ptr(void* v) : value_((T*)v) {}
+ T& operator*() const { return *value_; }
+};
+
+template <> struct ptr<void>
+{
+ void* value_;
+ ptr(void* v) : value_(v) {}
+};
+
+template <> struct ptr<const void>
+{
+ void const* value_;
+ ptr(void const* v) : value_(v) {}
+};
+
+template <typename T> struct allocator3
+{
+ typedef T value_type;
+ typedef ptr<T> pointer;
+ typedef ptr<T const> const_pointer;
+ typedef unsigned short size_type;
+
+ int x; // Just to make it non-empty, so that is_always_equal is false.
+
+ ALLOCATOR_METHODS_TYPEDEFS(allocator3)
+
+ typedef yes_type propagate_on_container_copy_assignment;
+ typedef no_type propagate_on_container_move_assignment;
+
+ allocator3<T> select_on_container_copy_construction() const
+ {
+ ++selected;
+ return allocator3<T>();
+ }
+};
+
+void test_allocator3()
+{
+ typedef allocator3<int> allocator;
+ typedef boost::unordered::detail::allocator_traits<allocator> traits;
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::size_type, unsigned short>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<traits::const_pointer, ptr<int const> >::value));
+ BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
+ BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
+ BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
+ BOOST_TEST(!traits::propagate_on_container_swap::value);
+ BOOST_TEST(!traits::is_always_equal::value);
+ BOOST_TEST(call_select<allocator>() == 1);
+}
+
+int main()
+{
+ test_empty_allocator();
+ test_allocator1();
+ test_allocator2();
+ test_allocator3();
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/unordered/test/unordered/assign_tests.cpp b/src/boost/libs/unordered/test/unordered/assign_tests.cpp
new file mode 100644
index 000000000..f3d633b0a
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/assign_tests.cpp
@@ -0,0 +1,297 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/test.hpp"
+#include "../objects/cxx11_allocator.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/equivalent.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+namespace assign_tests {
+
+ test::seed_t initialize_seed(96785);
+
+ template <class T> void assign_tests1(T*, test::random_generator generator)
+ {
+ typename T::hasher hf;
+ typename T::key_equal eq;
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n";
+ {
+ test::check_instances check_;
+
+ T x;
+ x = x;
+ BOOST_TEST(x.empty());
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(1000, generator);
+ T x(v.begin(), v.end());
+
+ test::ordered<T> tracker = test::create_ordered(x);
+ tracker.insert_range(v.begin(), v.end());
+
+ x = x;
+ tracker.compare(x);
+
+ T y;
+ y.max_load_factor(x.max_load_factor() / 20);
+ float mlf = x.max_load_factor();
+ y = x;
+ tracker.compare(x);
+ tracker.compare(y);
+ BOOST_TEST(x.max_load_factor() == mlf);
+ BOOST_TEST(y.max_load_factor() == mlf);
+ BOOST_TEST(y.load_factor() <= y.max_load_factor());
+ }
+ }
+
+ template <class T> void assign_tests2(T*, test::random_generator generator)
+ {
+ typename T::hasher hf1(1);
+ typename T::hasher hf2(2);
+ typename T::key_equal eq1(1);
+ typename T::key_equal eq2(2);
+ typename T::allocator_type al1(1);
+ typename T::allocator_type al2(2);
+
+ typedef typename T::allocator_type allocator_type;
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "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);
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(1000, generator);
+ T x1(v.begin(), v.end(), 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, v);
+ test::check_container(x2, v);
+ BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1a\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v1(0, generator);
+ test::random_values<T> v2(1000, generator);
+ T x1(0, hf2, eq2);
+ T x2(v2.begin(), v2.end(), 0, hf1, eq1);
+ x2 = x1;
+ BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
+ BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
+ BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
+ BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
+ test::check_container(x1, v1);
+ test::check_container(x2, v1);
+ BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.2\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v1(100, generator), v2(100, generator);
+ T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
+ T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
+ x2 = x1;
+ BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
+ if (allocator_type::is_propagate_on_assign) {
+ BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
+ BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
+ } else {
+ BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
+ BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
+ }
+ test::check_container(x1, v1);
+ test::check_container(x2, v1);
+ BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.3\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v1(100, generator), v2(1000, generator);
+ T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
+ T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
+ x2 = x1;
+ BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
+ if (allocator_type::is_propagate_on_assign) {
+ BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
+ BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
+ } else {
+ BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
+ BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
+ }
+ test::check_container(x1, v1);
+ test::check_container(x2, v1);
+ BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.4\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v1(1000, generator), v2(100, generator);
+ T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
+ T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
+ x2 = x1;
+ BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
+ if (allocator_type::is_propagate_on_assign) {
+ BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
+ BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
+ } else {
+ BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
+ BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
+ }
+ test::check_container(x1, v1);
+ test::check_container(x2, v1);
+ BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
+ }
+ }
+
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ std::allocator<test::object> >* test_map_std_alloc;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator1<test::object> >* test_multimap;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_assign> >*
+ test_set_prop_assign;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_assign> >*
+ test_multiset_prop_assign;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_assign> >*
+ test_map_prop_assign;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_assign> >*
+ test_multimap_prop_assign;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_assign> >*
+ test_set_no_prop_assign;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_assign> >*
+ test_multiset_no_prop_assign;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_assign> >*
+ test_map_no_prop_assign;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_assign> >*
+ test_multimap_no_prop_assign;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ template <typename T> bool is_propagate(T*)
+ {
+ return T::allocator_type::is_propagate_on_assign;
+ }
+
+ UNORDERED_AUTO_TEST (check_traits) {
+ BOOST_TEST(!is_propagate(test_set));
+ BOOST_TEST(is_propagate(test_set_prop_assign));
+ BOOST_TEST(!is_propagate(test_set_no_prop_assign));
+ }
+
+ UNORDERED_TEST(assign_tests1,
+ ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
+ test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(
+ test_multimap_prop_assign)(test_set_no_prop_assign)(
+ test_multiset_no_prop_assign)(test_map_no_prop_assign)(
+ test_multimap_no_prop_assign))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(
+ assign_tests2, ((test_set)(test_multiset)(test_map)(test_multimap)(
+ test_set_prop_assign)(test_multiset_prop_assign)(
+ test_map_prop_assign)(test_multimap_prop_assign)(
+ test_set_no_prop_assign)(test_multiset_no_prop_assign)(
+ test_map_no_prop_assign)(test_multimap_no_prop_assign))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
+ UNORDERED_AUTO_TEST (assign_default_initializer_list) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
+ std::initializer_list<std::pair<int const, int> > init;
+ boost::unordered_map<int, int> x1;
+ x1[25] = 3;
+ x1[16] = 10;
+ BOOST_TEST(!x1.empty());
+ x1 = init;
+ BOOST_TEST(x1.empty());
+ }
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ UNORDERED_AUTO_TEST (assign_initializer_list) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
+
+ boost::unordered_set<int> x;
+ x.insert(10);
+ x.insert(20);
+ x = {1, 2, -10};
+ BOOST_TEST(x.find(10) == x.end());
+ BOOST_TEST(x.find(-10) != x.end());
+ }
+
+#endif
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/at_tests.cpp b/src/boost/libs/unordered/test/unordered/at_tests.cpp
new file mode 100644
index 000000000..25b0951ad
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/at_tests.cpp
@@ -0,0 +1,67 @@
+
+// Copyright 2007-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include <string>
+
+namespace at_tests {
+
+ UNORDERED_AUTO_TEST (at_tests) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
+
+ boost::unordered_map<std::string, int> x;
+ boost::unordered_map<std::string, int> const& x_const(x);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
+
+ try {
+ x.at("one");
+ BOOST_ERROR("Should have thrown.");
+ } catch (std::out_of_range&) {
+ }
+
+ try {
+ x_const.at("one");
+ BOOST_ERROR("Should have thrown.");
+ } catch (std::out_of_range&) {
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
+
+ x["one"] = 1;
+ x["two"] = 2;
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check existing elements" << std::endl;
+
+ BOOST_TEST(x.at("one") == 1);
+ BOOST_TEST(x.at("two") == 2);
+ BOOST_TEST(x_const.at("one") == 1);
+ BOOST_TEST(x_const.at("two") == 2);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl;
+
+ try {
+ x.at("three");
+ BOOST_ERROR("Should have thrown.");
+ } catch (std::out_of_range&) {
+ }
+
+ try {
+ x_const.at("three");
+ BOOST_ERROR("Should have thrown.");
+ } catch (std::out_of_range&) {
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
+ }
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/bucket_tests.cpp b/src/boost/libs/unordered/test/unordered/bucket_tests.cpp
new file mode 100644
index 000000000..c314d2c56
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/bucket_tests.cpp
@@ -0,0 +1,94 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include <algorithm>
+#include "../objects/test.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/helpers.hpp"
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
+#pragma warning(disable : 4267) // conversion from 'size_t' to 'unsigned int',
+ // possible loss of data.
+#endif
+
+namespace bucket_tests {
+
+ test::seed_t initialize_seed(54635);
+
+ template <class X> void tests(X*, test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ typedef typename X::size_type size_type;
+ typedef typename X::const_local_iterator const_local_iterator;
+ test::random_values<X> v(1000, generator);
+
+ X x(v.begin(), v.end());
+
+ BOOST_TEST(x.bucket_count() <= x.max_bucket_count());
+ if (!(x.bucket_count() <= x.max_bucket_count())) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << x.bucket_count()
+ << "<=" << x.max_bucket_count() << "\n";
+ }
+
+ for (typename test::random_values<X>::const_iterator it = v.begin(),
+ end = v.end();
+ it != end; ++it) {
+ size_type bucket = x.bucket(test::get_key<X>(*it));
+
+ BOOST_TEST(bucket < x.bucket_count());
+ if (bucket < x.bucket_count()) {
+ // lit? lend?? I need a new naming scheme.
+ const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
+ while (lit != lend && test::get_key<X>(*it) != test::get_key<X>(*lit)) {
+ ++lit;
+ }
+ BOOST_TEST(lit != lend);
+ }
+ }
+
+ for (size_type i = 0; i < x.bucket_count(); ++i) {
+ BOOST_TEST(x.bucket_size(i) ==
+ static_cast<size_type>(std::distance(x.begin(i), x.end(i))));
+ BOOST_TEST(x.bucket_size(i) ==
+ static_cast<size_type>(std::distance(x.cbegin(i), x.cend(i))));
+ X const& x_ref = x;
+ BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
+ x_ref.begin(i), x_ref.end(i))));
+ BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
+ x_ref.cbegin(i), x_ref.cend(i))));
+ }
+ }
+
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator2<test::object> >* test_multimap;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(tests,
+ ((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(
+ test_multimap))((default_generator)(generate_collisions)(limited_range)))
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/compile_map.cpp b/src/boost/libs/unordered/test/unordered/compile_map.cpp
new file mode 100644
index 000000000..6a84d595a
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/compile_map.cpp
@@ -0,0 +1,248 @@
+
+// Copyright 2006-2009 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)
+
+// This test creates the containers with members that meet their minimum
+// requirements. Makes sure everything compiles and is defined correctly.
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/minimal.hpp"
+#include "./compile_tests.hpp"
+
+// Explicit instantiation to catch compile-time errors
+
+#define INSTANTIATE(type) \
+ template class boost::unordered::detail::instantiate_##type
+
+INSTANTIATE(map)<int, int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::allocator<int> >;
+INSTANTIATE(multimap)<int const, int const, boost::hash<int>,
+ std::equal_to<int>, test::minimal::allocator<int> >;
+
+INSTANTIATE(
+ map)<test::minimal::assignable const, test::minimal::default_assignable const,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<int> >;
+INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<int> >;
+
+UNORDERED_AUTO_TEST (test0) {
+ test::minimal::constructor_param x;
+
+ typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
+ value_type;
+ value_type value(x, x);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
+
+ boost::unordered_map<int, int> int_map;
+
+ boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<std::pair<int const, int> > >
+ int_map2;
+
+ boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<value_type> >
+ map;
+
+ container_test(int_map, std::pair<int const, int>(0, 0));
+ container_test(int_map2, std::pair<int const, int>(0, 0));
+ container_test(map, value);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
+
+ boost::unordered_multimap<int, int> int_multimap;
+
+ boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<std::pair<int const, int> > >
+ int_multimap2;
+
+ boost::unordered_multimap<test::minimal::assignable,
+ test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<value_type> >
+ multimap;
+
+ container_test(int_multimap, std::pair<int const, int>(0, 0));
+ container_test(int_multimap2, std::pair<int const, int>(0, 0));
+ container_test(multimap, value);
+}
+
+UNORDERED_AUTO_TEST (equality_tests) {
+ typedef std::pair<test::minimal::copy_constructible_equality_comparable const,
+ test::minimal::copy_constructible_equality_comparable>
+ value_type;
+
+ boost::unordered_map<int, int> int_map;
+
+ boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<std::pair<int const, int> > >
+ int_map2;
+
+ boost::unordered_map<test::minimal::copy_constructible_equality_comparable,
+ test::minimal::copy_constructible_equality_comparable,
+ test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
+ test::minimal::equal_to<
+ test::minimal::copy_constructible_equality_comparable>,
+ test::minimal::allocator<value_type> >
+ map;
+
+ equality_test(int_map);
+ equality_test(int_map2);
+ equality_test(map);
+
+ boost::unordered_multimap<int, int> int_multimap;
+
+ boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<std::pair<int const, int> > >
+ int_multimap2;
+
+ boost::unordered_multimap<
+ test::minimal::copy_constructible_equality_comparable,
+ test::minimal::copy_constructible_equality_comparable,
+ test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
+ test::minimal::equal_to<
+ test::minimal::copy_constructible_equality_comparable>,
+ test::minimal::allocator<value_type> >
+ multimap;
+
+ equality_test(int_multimap);
+ equality_test(int_multimap2);
+ equality_test(multimap);
+}
+
+UNORDERED_AUTO_TEST (test1) {
+ boost::hash<int> hash;
+ std::equal_to<int> equal_to;
+ int value = 0;
+ std::pair<int const, int> map_value(0, 0);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
+
+ boost::unordered_map<int, int> map;
+
+ boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<std::pair<int const, int> > >
+ map2;
+
+ unordered_unique_test(map, map_value);
+ unordered_map_test(map, value, value);
+ unordered_copyable_test(map, value, map_value, hash, equal_to);
+ unordered_map_functions(map, value, value);
+
+ unordered_unique_test(map2, map_value);
+ unordered_map_test(map2, value, value);
+ unordered_copyable_test(map2, value, map_value, hash, equal_to);
+ unordered_map_functions(map2, value, value);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
+
+ boost::unordered_multimap<int, int> multimap;
+
+ boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<std::pair<int const, int> > >
+ multimap2;
+
+ unordered_equivalent_test(multimap, map_value);
+ unordered_map_test(multimap, value, value);
+ unordered_copyable_test(multimap, value, map_value, hash, equal_to);
+
+ unordered_equivalent_test(multimap2, map_value);
+ unordered_map_test(multimap2, value, value);
+ unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
+}
+
+UNORDERED_AUTO_TEST (test2) {
+ test::minimal::constructor_param x;
+
+ test::minimal::assignable assignable(x);
+ test::minimal::copy_constructible copy_constructible(x);
+ test::minimal::hash<test::minimal::assignable> hash(x);
+ test::minimal::equal_to<test::minimal::assignable> equal_to(x);
+
+ typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
+ map_value_type;
+ map_value_type map_value(assignable, assignable);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
+
+ boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<map_value_type> >
+ map;
+
+ unordered_unique_test(map, map_value);
+ unordered_map_test(map, assignable, assignable);
+ unordered_copyable_test(map, assignable, map_value, hash, equal_to);
+ unordered_map_member_test(map, map_value);
+
+ boost::unordered_map<test::minimal::assignable,
+ test::minimal::default_assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<map_value_type> >
+ map2;
+
+ test::minimal::default_assignable default_assignable;
+
+ unordered_map_functions(map2, assignable, default_assignable);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
+
+ boost::unordered_multimap<test::minimal::assignable,
+ test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<map_value_type> >
+ multimap;
+
+ unordered_equivalent_test(multimap, map_value);
+ unordered_map_test(multimap, assignable, assignable);
+ unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
+ unordered_map_member_test(multimap, map_value);
+}
+
+// Test for ambiguity when using key convertible from iterator
+// See LWG2059
+
+struct lwg2059_key
+{
+ int value;
+
+ template <typename T> lwg2059_key(T v) : value(v) {}
+};
+
+std::size_t hash_value(lwg2059_key x)
+{
+ return static_cast<std::size_t>(x.value);
+}
+
+bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
+
+UNORDERED_AUTO_TEST (lwg2059) {
+ {
+ boost::unordered_map<lwg2059_key, int> x;
+ x.emplace(lwg2059_key(10), 5);
+ x.erase(x.begin());
+ }
+
+ {
+ boost::unordered_multimap<lwg2059_key, int> x;
+ x.emplace(lwg2059_key(10), 5);
+ x.erase(x.begin());
+ }
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/compile_set.cpp b/src/boost/libs/unordered/test/unordered/compile_set.cpp
new file mode 100644
index 000000000..727294f39
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/compile_set.cpp
@@ -0,0 +1,313 @@
+
+// Copyright 2006-2009 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)
+
+// This test creates the containers with members that meet their minimum
+// requirements. Makes sure everything compiles and is defined correctly.
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/minimal.hpp"
+#include "./compile_tests.hpp"
+
+// Explicit instantiation to catch compile-time errors
+
+#define INSTANTIATE(type) \
+ template class boost::unordered::detail::instantiate_##type
+
+INSTANTIATE(set)<int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::allocator<int> >;
+INSTANTIATE(multiset)<int const, boost::hash<int>, std::equal_to<int>,
+ test::minimal::allocator<int> >;
+
+INSTANTIATE(set)<test::minimal::assignable const,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<int> >;
+INSTANTIATE(multiset)<test::minimal::assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<int> >;
+
+UNORDERED_AUTO_TEST (test0) {
+ test::minimal::constructor_param x;
+
+ test::minimal::assignable assignable(x);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
+
+ boost::unordered_set<int> int_set;
+
+ boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<int> >
+ int_set2;
+
+ boost::unordered_set<test::minimal::assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<test::minimal::assignable> >
+ set;
+
+ container_test(int_set, 0);
+ container_test(int_set2, 0);
+ container_test(set, assignable);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
+
+ boost::unordered_multiset<int> int_multiset;
+
+ boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<int> >
+ int_multiset2;
+
+ boost::unordered_multiset<test::minimal::assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<test::minimal::assignable> >
+ multiset;
+
+ container_test(int_multiset, 0);
+ container_test(int_multiset2, 0);
+ container_test(multiset, assignable);
+}
+
+UNORDERED_AUTO_TEST (equality_tests) {
+ typedef test::minimal::copy_constructible_equality_comparable value_type;
+
+ boost::unordered_set<int> int_set;
+
+ boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<int> >
+ int_set2;
+
+ boost::unordered_set<test::minimal::copy_constructible_equality_comparable,
+ test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
+ test::minimal::equal_to<
+ test::minimal::copy_constructible_equality_comparable>,
+ test::minimal::allocator<value_type> >
+ set;
+
+ equality_test(int_set);
+ equality_test(int_set2);
+ equality_test(set);
+
+ boost::unordered_multiset<int> int_multiset;
+
+ boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<int> >
+ int_multiset2;
+
+ boost::unordered_multiset<
+ test::minimal::copy_constructible_equality_comparable,
+ test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
+ test::minimal::equal_to<
+ test::minimal::copy_constructible_equality_comparable>,
+ test::minimal::allocator<value_type> >
+ multiset;
+
+ equality_test(int_multiset);
+ equality_test(int_multiset2);
+ equality_test(multiset);
+}
+
+UNORDERED_AUTO_TEST (test1) {
+ boost::hash<int> hash;
+ std::equal_to<int> equal_to;
+ int value = 0;
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set." << std::endl;
+
+ boost::unordered_set<int> set;
+
+ boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<int> >
+ set2;
+
+ unordered_unique_test(set, value);
+ unordered_set_test(set, value);
+ unordered_copyable_test(set, value, value, hash, equal_to);
+
+ unordered_unique_test(set2, value);
+ unordered_set_test(set2, value);
+ unordered_copyable_test(set2, value, value, hash, equal_to);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset." << std::endl;
+
+ boost::unordered_multiset<int> multiset;
+
+ boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
+ test::minimal::cxx11_allocator<int> >
+ multiset2;
+
+ unordered_equivalent_test(multiset, value);
+ unordered_set_test(multiset, value);
+ unordered_copyable_test(multiset, value, value, hash, equal_to);
+
+ unordered_equivalent_test(multiset2, value);
+ unordered_set_test(multiset2, value);
+ unordered_copyable_test(multiset2, value, value, hash, equal_to);
+}
+
+UNORDERED_AUTO_TEST (test2) {
+ test::minimal::constructor_param x;
+
+ test::minimal::assignable assignable(x);
+ test::minimal::copy_constructible copy_constructible(x);
+ test::minimal::hash<test::minimal::assignable> hash(x);
+ test::minimal::equal_to<test::minimal::assignable> equal_to(x);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
+
+ boost::unordered_set<test::minimal::assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<test::minimal::assignable> >
+ set;
+
+ unordered_unique_test(set, assignable);
+ unordered_set_test(set, assignable);
+ unordered_copyable_test(set, assignable, assignable, hash, equal_to);
+ unordered_set_member_test(set, assignable);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
+
+ boost::unordered_multiset<test::minimal::assignable,
+ test::minimal::hash<test::minimal::assignable>,
+ test::minimal::equal_to<test::minimal::assignable>,
+ test::minimal::allocator<test::minimal::assignable> >
+ multiset;
+
+ unordered_equivalent_test(multiset, assignable);
+ unordered_set_test(multiset, assignable);
+ unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
+ unordered_set_member_test(multiset, assignable);
+}
+
+UNORDERED_AUTO_TEST (movable1_tests) {
+ test::minimal::constructor_param x;
+
+ test::minimal::movable1 movable1(x);
+ test::minimal::hash<test::minimal::movable1> hash(x);
+ test::minimal::equal_to<test::minimal::movable1> equal_to(x);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
+
+ boost::unordered_set<test::minimal::movable1,
+ test::minimal::hash<test::minimal::movable1>,
+ test::minimal::equal_to<test::minimal::movable1>,
+ test::minimal::allocator<test::minimal::movable1> >
+ set;
+
+ // unordered_unique_test(set, movable1);
+ unordered_set_test(set, movable1);
+ unordered_movable_test(set, movable1, movable1, hash, equal_to);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
+
+ boost::unordered_multiset<test::minimal::movable1,
+ test::minimal::hash<test::minimal::movable1>,
+ test::minimal::equal_to<test::minimal::movable1>,
+ test::minimal::allocator<test::minimal::movable1> >
+ multiset;
+
+ // unordered_equivalent_test(multiset, movable1);
+ unordered_set_test(multiset, movable1);
+ unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
+}
+
+UNORDERED_AUTO_TEST (movable2_tests) {
+ test::minimal::constructor_param x;
+
+ test::minimal::movable2 movable2(x);
+ test::minimal::hash<test::minimal::movable2> hash(x);
+ test::minimal::equal_to<test::minimal::movable2> equal_to(x);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
+
+ boost::unordered_set<test::minimal::movable2,
+ test::minimal::hash<test::minimal::movable2>,
+ test::minimal::equal_to<test::minimal::movable2>,
+ test::minimal::allocator<test::minimal::movable2> >
+ set;
+
+ // unordered_unique_test(set, movable2);
+ unordered_set_test(set, movable2);
+ unordered_movable_test(set, movable2, movable2, hash, equal_to);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
+
+ boost::unordered_multiset<test::minimal::movable2,
+ test::minimal::hash<test::minimal::movable2>,
+ test::minimal::equal_to<test::minimal::movable2>,
+ test::minimal::allocator<test::minimal::movable2> >
+ multiset;
+
+ // unordered_equivalent_test(multiset, movable2);
+ unordered_set_test(multiset, movable2);
+ unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
+}
+
+UNORDERED_AUTO_TEST (destructible_tests) {
+ test::minimal::constructor_param x;
+
+ test::minimal::destructible destructible(x);
+ test::minimal::hash<test::minimal::destructible> hash(x);
+ test::minimal::equal_to<test::minimal::destructible> equal_to(x);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
+
+ boost::unordered_set<test::minimal::destructible,
+ test::minimal::hash<test::minimal::destructible>,
+ test::minimal::equal_to<test::minimal::destructible> >
+ set;
+
+ unordered_destructible_test(set);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
+
+ boost::unordered_multiset<test::minimal::destructible,
+ test::minimal::hash<test::minimal::destructible>,
+ test::minimal::equal_to<test::minimal::destructible> >
+ multiset;
+
+ unordered_destructible_test(multiset);
+}
+
+// Test for ambiguity when using key convertible from iterator
+// See LWG2059
+
+struct lwg2059_key
+{
+ int value;
+
+ template <typename T> lwg2059_key(T v) : value(v) {}
+};
+
+std::size_t hash_value(lwg2059_key x)
+{
+ return static_cast<std::size_t>(x.value);
+}
+
+bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
+
+UNORDERED_AUTO_TEST (lwg2059) {
+ {
+ boost::unordered_set<lwg2059_key> x;
+ x.emplace(lwg2059_key(10));
+ x.erase(x.begin());
+ }
+
+ {
+ boost::unordered_multiset<lwg2059_key> x;
+ x.emplace(lwg2059_key(10));
+ x.erase(x.begin());
+ }
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/compile_tests.hpp b/src/boost/libs/unordered/test/unordered/compile_tests.hpp
new file mode 100644
index 000000000..bb5256f8b
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/compile_tests.hpp
@@ -0,0 +1,913 @@
+
+// Copyright 2005-2009 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)
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#pragma warning(disable : 4610) // class can never be instantiated
+#pragma warning(disable : 4510) // default constructor could not be generated
+#endif
+
+#include <boost/concept_check.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+#include "../helpers/check_return_type.hpp"
+#include <boost/core/pointer_traits.hpp>
+#include <boost/limits.hpp>
+#include <boost/predef.h>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/cv_traits.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/swap.hpp>
+
+typedef long double comparison_type;
+
+template <class T> void sink(T const&) {}
+template <class T> T rvalue(T const& v) { return v; }
+template <class T> T rvalue_default() { return T(); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+template <class T> T implicit_construct() { return {}; }
+#else
+template <class T> int implicit_construct()
+{
+ T x;
+ sink(x);
+ return 0;
+}
+#endif
+
+#if !defined(BOOST_NO_CXX11_NOEXCEPT)
+#define TEST_NOEXCEPT_EXPR(x) BOOST_STATIC_ASSERT((BOOST_NOEXCEPT_EXPR(x)));
+#else
+#define TEST_NOEXCEPT_EXPR(x)
+#endif
+
+template <class X, class T> void container_test(X& r, T const&)
+{
+ typedef typename X::iterator iterator;
+ typedef typename X::const_iterator const_iterator;
+ typedef typename X::difference_type difference_type;
+ typedef typename X::size_type size_type;
+
+ typedef
+ typename std::iterator_traits<iterator>::value_type iterator_value_type;
+ typedef typename std::iterator_traits<const_iterator>::value_type
+ const_iterator_value_type;
+ typedef typename std::iterator_traits<iterator>::difference_type
+ iterator_difference_type;
+ typedef typename std::iterator_traits<const_iterator>::difference_type
+ const_iterator_difference_type;
+
+ typedef typename X::value_type value_type;
+ typedef typename X::reference reference;
+ typedef typename X::const_reference const_reference;
+
+ typedef typename X::node_type node_type;
+
+ typedef typename X::allocator_type allocator_type;
+
+ // value_type
+
+ BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
+ boost::function_requires<boost::CopyConstructibleConcept<X> >();
+
+ // reference_type / const_reference_type
+
+ BOOST_STATIC_ASSERT((boost::is_same<T&, reference>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<T const&, const_reference>::value));
+
+ // iterator
+
+ boost::function_requires<boost::InputIteratorConcept<iterator> >();
+ BOOST_STATIC_ASSERT((boost::is_same<T, iterator_value_type>::value));
+ BOOST_STATIC_ASSERT((boost::is_convertible<iterator, const_iterator>::value));
+
+ // const_iterator
+
+ boost::function_requires<boost::InputIteratorConcept<const_iterator> >();
+ BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
+
+ // node_type
+
+ BOOST_STATIC_ASSERT((
+ boost::is_same<allocator_type, typename node_type::allocator_type>::value));
+
+ // difference_type
+
+ BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_signed);
+ BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_integer);
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<difference_type, iterator_difference_type>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<difference_type, const_iterator_difference_type>::value));
+
+ // size_type
+
+ BOOST_STATIC_ASSERT(!std::numeric_limits<size_type>::is_signed);
+ BOOST_STATIC_ASSERT(std::numeric_limits<size_type>::is_integer);
+
+ // size_type can represent any non-negative value type of difference_type
+ // I'm not sure about either of these tests...
+ size_type max_diff =
+ static_cast<size_type>((std::numeric_limits<difference_type>::max)());
+ difference_type converted_diff(static_cast<difference_type>(max_diff));
+ BOOST_TEST((std::numeric_limits<difference_type>::max)() == converted_diff);
+
+ BOOST_TEST(
+ static_cast<comparison_type>((std::numeric_limits<size_type>::max)()) >
+ static_cast<comparison_type>(
+ (std::numeric_limits<difference_type>::max)()));
+
+// Constructors
+
+// I don't test the runtime post-conditions here.
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ // It isn't specified in the container requirements that the no argument
+ // constructor is implicit, but it is defined that way in the concrete
+ // container specification.
+ X u_implicit = {};
+ sink(u_implicit);
+#endif
+
+ X u;
+ BOOST_TEST(u.size() == 0);
+ BOOST_TEST(X().size() == 0);
+
+ X a, b;
+ X a_const;
+
+ sink(X(a));
+ X u2(a);
+ X u3 = a;
+ X u4(rvalue(a_const));
+ X u5 = rvalue(a_const);
+
+ a.swap(b);
+ boost::swap(a, b);
+ test::check_return_type<X>::equals_ref(r = a);
+
+ // Allocator
+
+ test::check_return_type<allocator_type>::equals(a_const.get_allocator());
+
+ allocator_type m = a.get_allocator();
+ sink(X(m));
+ X c(m);
+ sink(X(a_const, m));
+ X c2(a_const, m);
+ sink(X(rvalue(a_const), m));
+ X c3(rvalue(a_const), m);
+
+ // node_type
+
+ implicit_construct<node_type const>();
+#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
+ TEST_NOEXCEPT_EXPR(node_type());
+#endif
+
+ node_type n1;
+ node_type n2(rvalue_default<node_type>());
+#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
+ TEST_NOEXCEPT_EXPR(node_type(boost::move(n1)));
+#endif
+ node_type n3;
+ n3 = boost::move(n2);
+ n1.swap(n3);
+ swap(n1, n3);
+ // TODO: noexcept for swap?
+ // value, key, mapped tests in map and set specific testing.
+
+ node_type const n_const;
+ BOOST_TEST(n_const ? 0 : 1);
+ TEST_NOEXCEPT_EXPR(n_const ? 0 : 1);
+ test::check_return_type<bool>::equals(!n_const);
+ test::check_return_type<bool>::equals(n_const.empty());
+ TEST_NOEXCEPT_EXPR(!n_const);
+ TEST_NOEXCEPT_EXPR(n_const.empty());
+
+ // Avoid unused variable warnings:
+
+ sink(u);
+ sink(u2);
+ sink(u3);
+ sink(u4);
+ sink(u5);
+ sink(c);
+ sink(c2);
+ sink(c3);
+}
+
+template <class X> void unordered_destructible_test(X&)
+{
+ typedef typename X::iterator iterator;
+ typedef typename X::const_iterator const_iterator;
+ typedef typename X::size_type size_type;
+
+ X x1;
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ X x2(rvalue_default<X>());
+ X x3 = rvalue_default<X>();
+// This can only be done if propagate_on_container_move_assignment::value
+// is true.
+// x2 = rvalue_default<X>();
+#endif
+
+ X* ptr = new X();
+ X& a1 = *ptr;
+ (&a1)->~X();
+ ::operator delete((void*)(&a1));
+
+ X a, b;
+ X const a_const;
+ test::check_return_type<iterator>::equals(a.begin());
+ test::check_return_type<const_iterator>::equals(a_const.begin());
+ test::check_return_type<const_iterator>::equals(a.cbegin());
+ test::check_return_type<const_iterator>::equals(a_const.cbegin());
+ test::check_return_type<iterator>::equals(a.end());
+ test::check_return_type<const_iterator>::equals(a_const.end());
+ test::check_return_type<const_iterator>::equals(a.cend());
+ test::check_return_type<const_iterator>::equals(a_const.cend());
+
+ a.swap(b);
+ boost::swap(a, b);
+
+ test::check_return_type<size_type>::equals(a.size());
+ test::check_return_type<size_type>::equals(a.max_size());
+ test::check_return_type<bool>::convertible(a.empty());
+
+ // Allocator
+
+ typedef typename X::allocator_type allocator_type;
+ test::check_return_type<allocator_type>::equals(a_const.get_allocator());
+}
+
+template <class X, class Key> void unordered_set_test(X& r, Key const&)
+{
+ typedef typename X::value_type value_type;
+ typedef typename X::key_type key_type;
+
+ BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
+
+ // iterator pointer / const_pointer_type
+
+ typedef typename X::iterator iterator;
+ typedef typename X::const_iterator const_iterator;
+ typedef typename X::local_iterator local_iterator;
+ typedef typename X::const_local_iterator const_local_iterator;
+ typedef typename std::iterator_traits<iterator>::pointer iterator_pointer;
+ typedef typename std::iterator_traits<const_iterator>::pointer
+ const_iterator_pointer;
+ typedef typename std::iterator_traits<local_iterator>::pointer
+ local_iterator_pointer;
+ typedef typename std::iterator_traits<const_local_iterator>::pointer
+ const_local_iterator_pointer;
+
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<value_type const*, iterator_pointer>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<value_type const*, const_iterator_pointer>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<value_type const*, local_iterator_pointer>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<value_type const*, const_local_iterator_pointer>::value));
+
+ // pointer_traits<iterator>
+
+ BOOST_STATIC_ASSERT((boost::is_same<iterator,
+ typename boost::pointer_traits<iterator>::pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<value_type const,
+ typename boost::pointer_traits<iterator>::element_type>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
+ typename boost::pointer_traits<iterator>::difference_type>::value));
+
+ // pointer_traits<const_iterator>
+
+ BOOST_STATIC_ASSERT((boost::is_same<const_iterator,
+ typename boost::pointer_traits<const_iterator>::pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<value_type const,
+ typename boost::pointer_traits<const_iterator>::element_type>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
+ typename boost::pointer_traits<const_iterator>::difference_type>::value));
+
+ // pointer_traits<local_iterator>
+
+ BOOST_STATIC_ASSERT((boost::is_same<local_iterator,
+ typename boost::pointer_traits<local_iterator>::pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<value_type const,
+ typename boost::pointer_traits<local_iterator>::element_type>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
+ typename boost::pointer_traits<local_iterator>::difference_type>::value));
+
+ // pointer_traits<const_local_iterator>
+
+ BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator,
+ typename boost::pointer_traits<const_local_iterator>::pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<value_type const,
+ typename boost::pointer_traits<const_local_iterator>::element_type>::
+ value));
+ BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
+ typename boost::pointer_traits<const_local_iterator>::difference_type>::
+ value));
+
+ typedef typename X::node_type node_type;
+ typedef typename node_type::value_type node_value_type;
+ BOOST_STATIC_ASSERT((boost::is_same<value_type, node_value_type>::value));
+
+ // Call node_type functions.
+
+ test::minimal::constructor_param v;
+ Key k_lvalue(v);
+ r.emplace(boost::move(k_lvalue));
+ node_type n1 = r.extract(r.begin());
+ test::check_return_type<value_type>::equals_ref(n1.value());
+}
+
+template <class X, class Key, class T>
+void unordered_map_test(X& r, Key const& k, T const& v)
+{
+ typedef typename X::value_type value_type;
+ typedef typename X::key_type key_type;
+
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<value_type, std::pair<key_type const, T> >::value));
+
+ // iterator pointer / const_pointer_type
+
+ typedef typename X::iterator iterator;
+ typedef typename X::const_iterator const_iterator;
+ typedef typename X::local_iterator local_iterator;
+ typedef typename X::const_local_iterator const_local_iterator;
+ typedef typename std::iterator_traits<iterator>::pointer iterator_pointer;
+ typedef typename std::iterator_traits<const_iterator>::pointer
+ const_iterator_pointer;
+ typedef typename std::iterator_traits<local_iterator>::pointer
+ local_iterator_pointer;
+ typedef typename std::iterator_traits<const_local_iterator>::pointer
+ const_local_iterator_pointer;
+
+ BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<value_type const*, const_iterator_pointer>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<value_type*, local_iterator_pointer>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<value_type const*, const_local_iterator_pointer>::value));
+
+ // pointer_traits<iterator>
+
+ BOOST_STATIC_ASSERT((boost::is_same<iterator,
+ typename boost::pointer_traits<iterator>::pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<value_type,
+ typename boost::pointer_traits<iterator>::element_type>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
+ typename boost::pointer_traits<iterator>::difference_type>::value));
+
+ // pointer_traits<const_iterator>
+
+ BOOST_STATIC_ASSERT((boost::is_same<const_iterator,
+ typename boost::pointer_traits<const_iterator>::pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<value_type const,
+ typename boost::pointer_traits<const_iterator>::element_type>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
+ typename boost::pointer_traits<const_iterator>::difference_type>::value));
+
+ // pointer_traits<local_iterator>
+
+ BOOST_STATIC_ASSERT((boost::is_same<local_iterator,
+ typename boost::pointer_traits<local_iterator>::pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<value_type,
+ typename boost::pointer_traits<local_iterator>::element_type>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
+ typename boost::pointer_traits<local_iterator>::difference_type>::value));
+
+ // pointer_traits<const_local_iterator>
+
+ BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator,
+ typename boost::pointer_traits<const_local_iterator>::pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<value_type const,
+ typename boost::pointer_traits<const_local_iterator>::element_type>::
+ value));
+ BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
+ typename boost::pointer_traits<const_local_iterator>::difference_type>::
+ value));
+
+ typedef typename X::node_type node_type;
+ typedef typename node_type::key_type node_key_type;
+ typedef typename node_type::mapped_type node_mapped_type;
+
+ BOOST_STATIC_ASSERT((boost::is_same<Key, node_key_type>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<T, node_mapped_type>::value));
+ // Superfluous,but just to make sure.
+ BOOST_STATIC_ASSERT((!boost::is_const<node_key_type>::value));
+
+ // Calling functions
+
+ r.insert(std::pair<Key const, T>(k, v));
+ r.insert(r.begin(), std::pair<Key const, T>(k, v));
+ std::pair<Key const, T> const value(k, v);
+ r.insert(value);
+ r.insert(r.end(), value);
+
+ Key k_lvalue(k);
+ T v_lvalue(v);
+
+ // Emplace
+
+ r.emplace(k, v);
+ r.emplace(k_lvalue, v_lvalue);
+ r.emplace(rvalue(k), rvalue(v));
+
+ r.emplace(boost::unordered::piecewise_construct, boost::make_tuple(k),
+ boost::make_tuple(v));
+
+ // Emplace with hint
+
+ r.emplace_hint(r.begin(), k, v);
+ r.emplace_hint(r.begin(), k_lvalue, v_lvalue);
+ r.emplace_hint(r.begin(), rvalue(k), rvalue(v));
+
+ r.emplace_hint(r.begin(), boost::unordered::piecewise_construct,
+ boost::make_tuple(k), boost::make_tuple(v));
+
+ // Extract
+
+ test::check_return_type<node_type>::equals(r.extract(r.begin()));
+
+ r.emplace(k, v);
+ test::check_return_type<node_type>::equals(r.extract(k));
+
+ r.emplace(k, v);
+ node_type n1 = r.extract(r.begin());
+ test::check_return_type<key_type>::equals_ref(n1.key());
+ test::check_return_type<T>::equals_ref(n1.mapped());
+
+ node_type n2 = boost::move(n1);
+ r.insert(boost::move(n2));
+ r.insert(r.extract(r.begin()));
+ n2 = r.extract(r.begin());
+ r.insert(r.begin(), boost::move(n2));
+ r.insert(r.end(), r.extract(r.begin()));
+
+ node_type n = r.extract(r.begin());
+ test::check_return_type<node_key_type>::equals_ref(n.key());
+ test::check_return_type<node_mapped_type>::equals_ref(n.mapped());
+}
+
+template <class X> void equality_test(X& r)
+{
+ X const a = r, b = r;
+
+ test::check_return_type<bool>::equals(a == b);
+ test::check_return_type<bool>::equals(a != b);
+ test::check_return_type<bool>::equals(boost::operator==(a, b));
+ test::check_return_type<bool>::equals(boost::operator!=(a, b));
+}
+
+template <class X, class T> void unordered_unique_test(X& r, T const& t)
+{
+ typedef typename X::iterator iterator;
+ test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t));
+ test::check_return_type<std::pair<iterator, bool> >::equals(r.emplace(t));
+
+ typedef typename X::node_type node_type;
+ typedef typename X::insert_return_type insert_return_type;
+
+ // insert_return_type
+
+ // TODO;
+ // boost::function_requires<
+ // boost::MoveConstructibleConcept<insert_return_type>
+ // >();
+ // TODO;
+ // boost::function_requires<
+ // boost::MoveAssignableConcept<insert_return_type>
+ // >();
+ boost::function_requires<
+ boost::DefaultConstructibleConcept<insert_return_type> >();
+ // TODO:
+ // boost::function_requires<
+ // boost::DestructibleConcept<insert_return_type>
+ // >();
+ insert_return_type insert_return, insert_return2;
+ test::check_return_type<bool>::equals(insert_return.inserted);
+ test::check_return_type<iterator>::equals(insert_return.position);
+ test::check_return_type<node_type>::equals_ref(insert_return.node);
+ boost::swap(insert_return, insert_return2);
+}
+
+template <class X, class T> void unordered_equivalent_test(X& r, T const& t)
+{
+ typedef typename X::iterator iterator;
+ test::check_return_type<iterator>::equals(r.insert(t));
+ test::check_return_type<iterator>::equals(r.emplace(t));
+}
+
+template <class X, class Key, class T>
+void unordered_map_functions(X&, Key const& k, T const& v)
+{
+ typedef typename X::mapped_type mapped_type;
+ typedef typename X::iterator iterator;
+
+ X a;
+ test::check_return_type<mapped_type>::equals_ref(a[k]);
+ test::check_return_type<mapped_type>::equals_ref(a[rvalue(k)]);
+ test::check_return_type<mapped_type>::equals_ref(a.at(k));
+ test::check_return_type<std::pair<iterator, bool> >::equals(
+ a.try_emplace(k, v));
+ test::check_return_type<std::pair<iterator, bool> >::equals(
+ a.try_emplace(rvalue(k), v));
+ test::check_return_type<iterator>::equals(a.try_emplace(a.begin(), k, v));
+ test::check_return_type<iterator>::equals(
+ a.try_emplace(a.begin(), rvalue(k), v));
+ test::check_return_type<std::pair<iterator, bool> >::equals(
+ a.insert_or_assign(k, v));
+ test::check_return_type<std::pair<iterator, bool> >::equals(
+ a.insert_or_assign(rvalue(k), v));
+ test::check_return_type<iterator>::equals(
+ a.insert_or_assign(a.begin(), k, v));
+ test::check_return_type<iterator>::equals(
+ a.insert_or_assign(a.begin(), rvalue(k), v));
+
+ X const b = a;
+ test::check_return_type<mapped_type const>::equals_ref(b.at(k));
+}
+
+template <class X, class Key, class Hash, class Pred>
+void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
+{
+ unordered_destructible_test(x);
+
+ typedef typename X::key_type key_type;
+ typedef typename X::hasher hasher;
+ typedef typename X::key_equal key_equal;
+ typedef typename X::size_type size_type;
+
+ typedef typename X::iterator iterator;
+ typedef typename X::const_iterator const_iterator;
+ typedef typename X::local_iterator local_iterator;
+ typedef typename X::const_local_iterator const_local_iterator;
+
+ typedef typename std::iterator_traits<iterator>::iterator_category
+ iterator_category;
+ typedef typename std::iterator_traits<iterator>::difference_type
+ iterator_difference;
+ typedef typename std::iterator_traits<iterator>::pointer iterator_pointer;
+ typedef typename std::iterator_traits<iterator>::reference iterator_reference;
+
+ typedef typename std::iterator_traits<local_iterator>::iterator_category
+ local_iterator_category;
+ typedef typename std::iterator_traits<local_iterator>::difference_type
+ local_iterator_difference;
+ typedef typename std::iterator_traits<local_iterator>::pointer
+ local_iterator_pointer;
+ typedef typename std::iterator_traits<local_iterator>::reference
+ local_iterator_reference;
+
+ typedef typename std::iterator_traits<const_iterator>::iterator_category
+ const_iterator_category;
+ typedef typename std::iterator_traits<const_iterator>::difference_type
+ const_iterator_difference;
+ typedef typename std::iterator_traits<const_iterator>::pointer
+ const_iterator_pointer;
+ typedef typename std::iterator_traits<const_iterator>::reference
+ const_iterator_reference;
+
+ typedef typename std::iterator_traits<const_local_iterator>::iterator_category
+ const_local_iterator_category;
+ typedef typename std::iterator_traits<const_local_iterator>::difference_type
+ const_local_iterator_difference;
+ typedef typename std::iterator_traits<const_local_iterator>::pointer
+ const_local_iterator_pointer;
+ typedef typename std::iterator_traits<const_local_iterator>::reference
+ const_local_iterator_reference;
+ typedef typename X::allocator_type allocator_type;
+
+ BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
+ // boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
+ // boost::function_requires<boost::AssignableConcept<key_type> >();
+
+ BOOST_STATIC_ASSERT((boost::is_same<Hash, hasher>::value));
+ test::check_return_type<std::size_t>::equals(hf(k));
+
+ BOOST_STATIC_ASSERT((boost::is_same<Pred, key_equal>::value));
+ test::check_return_type<bool>::convertible(eq(k, k));
+
+ boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<local_iterator_category, iterator_category>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<local_iterator_difference, iterator_difference>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<local_iterator_pointer, iterator_pointer>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<local_iterator_reference, iterator_reference>::value));
+
+ boost::function_requires<
+ boost::InputIteratorConcept<const_local_iterator> >();
+ BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_category,
+ const_iterator_category>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_difference,
+ const_iterator_difference>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_pointer,
+ const_iterator_pointer>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
+ const_iterator_reference>::value));
+
+ X a;
+ allocator_type m = a.get_allocator();
+
+ // Constructors
+
+ X(10, hf, eq);
+ X a1(10, hf, eq);
+ X(10, hf);
+ X a2(10, hf);
+ X(10);
+ X a3(10);
+ X();
+ X a4;
+
+ X(10, hf, eq, m);
+ X a1a(10, hf, eq, m);
+ X(10, hf, m);
+ X a2a(10, hf, m);
+ X(10, m);
+ X a3a(10, m);
+ (X(m));
+ X a4a(m);
+
+ test::check_return_type<size_type>::equals(a.erase(k));
+
+ const_iterator q1 = a.cbegin(), q2 = a.cend();
+ test::check_return_type<iterator>::equals(a.erase(q1, q2));
+
+ TEST_NOEXCEPT_EXPR(a.clear());
+ a.clear();
+
+ X const b;
+
+ test::check_return_type<hasher>::equals(b.hash_function());
+ test::check_return_type<key_equal>::equals(b.key_eq());
+
+ test::check_return_type<iterator>::equals(a.find(k));
+ test::check_return_type<const_iterator>::equals(b.find(k));
+ test::check_return_type<size_type>::equals(b.count(k));
+ test::check_return_type<std::pair<iterator, iterator> >::equals(
+ a.equal_range(k));
+ test::check_return_type<std::pair<const_iterator, const_iterator> >::equals(
+ b.equal_range(k));
+ test::check_return_type<size_type>::equals(b.bucket_count());
+ test::check_return_type<size_type>::equals(b.max_bucket_count());
+ test::check_return_type<size_type>::equals(b.bucket(k));
+ test::check_return_type<size_type>::equals(b.bucket_size(0));
+
+ test::check_return_type<local_iterator>::equals(a.begin(0));
+ test::check_return_type<const_local_iterator>::equals(b.begin(0));
+ test::check_return_type<local_iterator>::equals(a.end(0));
+ test::check_return_type<const_local_iterator>::equals(b.end(0));
+
+ test::check_return_type<const_local_iterator>::equals(a.cbegin(0));
+ test::check_return_type<const_local_iterator>::equals(b.cbegin(0));
+ test::check_return_type<const_local_iterator>::equals(a.cend(0));
+ test::check_return_type<const_local_iterator>::equals(b.cend(0));
+
+ test::check_return_type<float>::equals(b.load_factor());
+ test::check_return_type<float>::equals(b.max_load_factor());
+ a.max_load_factor((float)2.0);
+ a.rehash(100);
+
+ a.merge(a2);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ a.merge(rvalue_default<X>());
+#endif
+
+ // Avoid unused variable warnings:
+
+ sink(a);
+ sink(a1);
+ sink(a2);
+ sink(a3);
+ sink(a4);
+ sink(a1a);
+ sink(a2a);
+ sink(a3a);
+ sink(a4a);
+}
+
+template <class X, class Key, class T, class Hash, class Pred>
+void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
+{
+ unordered_test(x, k, hf, eq);
+
+ typedef typename X::iterator iterator;
+ typedef typename X::const_iterator const_iterator;
+ typedef typename X::allocator_type allocator_type;
+
+ X a;
+ allocator_type m = a.get_allocator();
+
+ typename X::value_type* i = 0;
+ typename X::value_type* j = 0;
+
+ // Constructors
+
+ X(i, j, 10, hf, eq);
+ X a5(i, j, 10, hf, eq);
+ X(i, j, 10, hf);
+ X a6(i, j, 10, hf);
+ X(i, j, 10);
+ X a7(i, j, 10);
+ X(i, j);
+ X a8(i, j);
+
+ X(i, j, 10, hf, eq, m);
+ X a5a(i, j, 10, hf, eq, m);
+ X(i, j, 10, hf, m);
+ X a6a(i, j, 10, hf, m);
+ X(i, j, 10, m);
+ X a7a(i, j, 10, m);
+
+// Not specified for some reason (maybe ambiguity with another constructor?)
+// X(i, j, m);
+// X a8a(i, j, m);
+// sink(a8a);
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ std::size_t min_buckets = 10;
+ X({t});
+ X({t}, min_buckets);
+ X({t}, min_buckets, hf);
+ X({t}, min_buckets, hf, eq);
+ // X({t}, m);
+ X({t}, min_buckets, m);
+ X({t}, min_buckets, hf, m);
+ X({t}, min_buckets, hf, eq, m);
+#endif
+
+ X const b;
+ sink(X(b));
+ X a9(b);
+ a = b;
+
+ sink(X(b, m));
+ X a9a(b, m);
+
+ X b1;
+ b1.insert(t);
+ X a9b(b1);
+ sink(a9b);
+ X a9c(b1, m);
+ sink(a9c);
+
+ const_iterator q = a.cbegin();
+
+ test::check_return_type<iterator>::equals(a.insert(q, t));
+ test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
+
+ a.insert(i, j);
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ std::initializer_list<T> list = {t};
+ a.insert(list);
+ a.insert({t, t, t});
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) && \
+ (!defined(__clang__) || __clang_major__ >= 4 || \
+ (__clang_major__ == 3 && __clang_minor__ >= 4))
+ a.insert({});
+ a.insert({t});
+ a.insert({t, t});
+#endif
+#endif
+
+ X a10;
+ a10.insert(t);
+ q = a10.cbegin();
+ test::check_return_type<iterator>::equals(a10.erase(q));
+
+ // Avoid unused variable warnings:
+
+ sink(a);
+ sink(a5);
+ sink(a6);
+ sink(a7);
+ sink(a8);
+ sink(a9);
+ sink(a5a);
+ sink(a6a);
+ sink(a7a);
+ sink(a9a);
+
+ typedef typename X::node_type node_type;
+ typedef typename X::allocator_type allocator_type;
+ node_type const n_const = a.extract(a.begin());
+ test::check_return_type<allocator_type>::equals(n_const.get_allocator());
+}
+
+template <class X, class Key, class T, class Hash, class Pred>
+void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
+{
+ unordered_test(x, k, hf, eq);
+
+ typedef typename X::iterator iterator;
+ typedef typename X::const_iterator const_iterator;
+ typedef typename X::allocator_type allocator_type;
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ X x1(rvalue_default<X>());
+ X x2(boost::move(x1));
+ x1 = rvalue_default<X>();
+ x2 = boost::move(x1);
+#endif
+
+ X a;
+ allocator_type m = a.get_allocator();
+
+ test::minimal::constructor_param* i = 0;
+ test::minimal::constructor_param* j = 0;
+
+ // Constructors
+
+ X(i, j, 10, hf, eq);
+ X a5(i, j, 10, hf, eq);
+ X(i, j, 10, hf);
+ X a6(i, j, 10, hf);
+ X(i, j, 10);
+ X a7(i, j, 10);
+ X(i, j);
+ X a8(i, j);
+
+ X(i, j, 10, hf, eq, m);
+ X a5a(i, j, 10, hf, eq, m);
+ X(i, j, 10, hf, m);
+ X a6a(i, j, 10, hf, m);
+ X(i, j, 10, m);
+ X a7a(i, j, 10, m);
+
+ // Not specified for some reason (maybe ambiguity with another constructor?)
+ // X(i, j, m);
+ // X a8a(i, j, m);
+ // sink(a8a);
+
+ const_iterator q = a.cbegin();
+
+ test::minimal::constructor_param v;
+ a.emplace(v);
+ test::check_return_type<iterator>::equals(a.emplace_hint(q, v));
+
+ T v1(v);
+ a.emplace(boost::move(v1));
+ T v2(v);
+ a.insert(boost::move(v2));
+ T v3(v);
+ test::check_return_type<iterator>::equals(a.emplace_hint(q, boost::move(v3)));
+ T v4(v);
+ test::check_return_type<iterator>::equals(a.insert(q, boost::move(v4)));
+
+ a.insert(i, j);
+
+ X a10;
+ T v5(v);
+ a10.insert(boost::move(v5));
+ q = a10.cbegin();
+ test::check_return_type<iterator>::equals(a10.erase(q));
+
+ // Avoid unused variable warnings:
+
+ sink(a);
+ sink(a5);
+ sink(a6);
+ sink(a7);
+ sink(a8);
+ sink(a5a);
+ sink(a6a);
+ sink(a7a);
+ sink(a10);
+}
+
+template <class X, class T> void unordered_set_member_test(X& x, T& t)
+{
+ X x1(x);
+ x1.insert(t);
+ x1.begin()->dummy_member();
+ x1.cbegin()->dummy_member();
+}
+
+template <class X, class T> void unordered_map_member_test(X& x, T& t)
+{
+ X x1(x);
+ x1.insert(t);
+ x1.begin()->first.dummy_member();
+ x1.cbegin()->first.dummy_member();
+ x1.begin()->second.dummy_member();
+ x1.cbegin()->second.dummy_member();
+}
diff --git a/src/boost/libs/unordered/test/unordered/constructor_tests.cpp b/src/boost/libs/unordered/test/unordered/constructor_tests.cpp
new file mode 100644
index 000000000..5f5719864
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/constructor_tests.cpp
@@ -0,0 +1,446 @@
+
+// Copyright 2006-2010 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/test.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/equivalent.hpp"
+#include "../helpers/input_iterator.hpp"
+#include "../helpers/invariants.hpp"
+
+namespace constructor_tests {
+
+ test::seed_t initialize_seed(356730);
+
+ template <class T>
+ void constructor_tests1(T*, test::random_generator generator)
+ {
+ typename T::hasher hf;
+ typename T::key_equal eq;
+ typename T::allocator_type al;
+
+ UNORDERED_SUB_TEST("Construct 1")
+ {
+ test::check_instances check_;
+
+ T x(0, hf, eq);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 2")
+ {
+ test::check_instances check_;
+
+ T x(100, hf);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.bucket_count() >= 100);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 3")
+ {
+ test::check_instances check_;
+
+ T x(2000);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.bucket_count() >= 2000);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 4")
+ {
+ test::check_instances check_;
+
+ T x;
+ BOOST_TEST(x.empty());
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 5")
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(1000, generator);
+ T x(v.begin(), v.end(), 10000, hf, eq);
+ BOOST_TEST(x.bucket_count() >= 10000);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 6")
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(10, generator);
+ T x(v.begin(), v.end(), 10000, hf);
+ BOOST_TEST(x.bucket_count() >= 10000);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 7")
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(100, generator);
+ T x(v.begin(), v.end(), 100);
+ BOOST_TEST(x.bucket_count() >= 100);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 8")
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(1, generator);
+ T x(v.begin(), v.end());
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 9")
+ {
+ test::check_instances check_;
+
+ T x(0, hf, eq, al);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 10")
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(1000, generator);
+ T x(v.begin(), v.end(), 10000, hf, eq, al);
+ BOOST_TEST(x.bucket_count() >= 10000);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 11")
+ {
+ test::check_instances check_;
+
+ T x(al);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_equivalent_keys(x);
+ }
+ }
+
+ template <class T>
+ void constructor_tests2(T*, test::random_generator const& generator)
+ {
+ typename T::hasher hf;
+ typename T::hasher hf1(1);
+ typename T::hasher hf2(2);
+ typename T::key_equal eq;
+ typename T::key_equal eq1(1);
+ typename T::key_equal eq2(2);
+ typename T::allocator_type al;
+ typename T::allocator_type al1(1);
+ typename T::allocator_type al2(2);
+
+ UNORDERED_SUB_TEST("Construct 1")
+ {
+ test::check_instances check_;
+ T x(10000, hf1, eq1);
+ BOOST_TEST(x.bucket_count() >= 10000);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq1));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 2")
+ {
+ test::check_instances check_;
+ T x(100, hf1);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.bucket_count() >= 100);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 3")
+ {
+ test::check_instances check_;
+ test::random_values<T> v(100, generator);
+ T x(v.begin(), v.end(), 0, hf1, eq1);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq1));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 4")
+ {
+ test::check_instances check_;
+ test::random_values<T> v(5, generator);
+ T x(v.begin(), v.end(), 1000, hf1);
+ BOOST_TEST(x.bucket_count() >= 1000);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("Construct 5")
+ {
+ test::check_instances check_;
+ test::random_values<T> v(100, generator);
+ T x(v.begin(), v.end(), 0, hf, eq, al1);
+ T y(x.begin(), x.end(), 0, hf1, eq1, al2);
+ test::check_container(x, v);
+ test::check_container(y, x);
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ }
+
+ UNORDERED_SUB_TEST("Construct 6")
+ {
+ test::check_instances check_;
+ test::random_values<T> v(100, generator);
+ T x(v.begin(), v.end(), 0, hf1, eq1);
+ T y(x.begin(), x.end(), 0, hf, eq);
+ test::check_container(x, v);
+ test::check_container(y, x);
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ }
+
+ UNORDERED_SUB_TEST("Construct 7")
+ {
+ test::check_instances check_;
+ test::random_values<T> v(100, generator);
+ T x(v.begin(), v.end(), 0, hf1, eq1);
+ T y(x.begin(), x.end(), 0, hf2, eq2);
+ test::check_container(x, v);
+ test::check_container(y, x);
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ }
+
+ UNORDERED_SUB_TEST("Construct 8 - from input iterator")
+ {
+ test::check_instances check_;
+ test::random_values<T> v(100, generator);
+ 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);
+ 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);
+ test::check_equivalent_keys(y);
+ }
+
+ UNORDERED_SUB_TEST("Construct 8.5 - from copy iterator")
+ {
+ test::check_instances check_;
+ test::random_values<T> v(100, generator);
+ T x(test::copy_iterator(v.begin()), test::copy_iterator(v.end()), 0, hf1,
+ eq1);
+ T y(test::copy_iterator(x.begin()), test::copy_iterator(x.end()), 0, hf2,
+ eq2);
+ test::check_container(x, v);
+ test::check_container(y, x);
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ }
+
+ UNORDERED_SUB_TEST("Construct 9")
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(100, generator);
+ T x(50);
+ BOOST_TEST(x.bucket_count() >= 50);
+ x.max_load_factor(10);
+ BOOST_TEST(x.bucket_count() >= 50);
+ x.insert(v.begin(), v.end());
+ BOOST_TEST(x.bucket_count() >= 50);
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ std::initializer_list<typename T::value_type> list;
+
+ UNORDERED_SUB_TEST("Initializer list construct 1")
+ {
+ test::check_instances check_;
+
+ T x(list);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ }
+
+ UNORDERED_SUB_TEST("Initializer list construct 2")
+ {
+ test::check_instances check_;
+
+ T x(list, 1000);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.bucket_count() >= 1000);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ }
+
+ UNORDERED_SUB_TEST("Initializer list construct 3")
+ {
+ test::check_instances check_;
+
+ T x(list, 10, hf1);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.bucket_count() >= 10);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ }
+
+ UNORDERED_SUB_TEST("Initializer list construct 4")
+ {
+ test::check_instances check_;
+
+ T x(list, 10, hf1, eq1);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.bucket_count() >= 10);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq1));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al));
+ }
+
+ UNORDERED_SUB_TEST("Initializer list construct 5")
+ {
+ test::check_instances check_;
+
+ T x(list, 10, hf1, eq1, al1);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.bucket_count() >= 10);
+ BOOST_TEST(test::equivalent(x.hash_function(), hf1));
+ BOOST_TEST(test::equivalent(x.key_eq(), eq1));
+ BOOST_TEST(test::equivalent(x.get_allocator(), al1));
+ }
+#endif
+ }
+
+ template <class T>
+ void map_constructor_test(T*, test::random_generator const& generator)
+ {
+ typedef test::list<
+ std::pair<typename T::key_type, typename T::mapped_type> >
+ list;
+ test::random_values<T> v(1000, generator);
+ list l(v.begin(), v.end());
+ T x(l.begin(), l.end());
+
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ std::allocator<test::object> >* test_map_std_alloc;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator1<test::object> >* test_multimap;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(constructor_tests1,
+ ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(constructor_tests2,
+ ((test_set)(test_multiset)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(map_constructor_test,
+ ((test_map_std_alloc)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
+ UNORDERED_AUTO_TEST (test_default_initializer_list) {
+ std::initializer_list<int> init;
+ boost::unordered_set<int> x1 = init;
+ BOOST_TEST(x1.empty());
+ }
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
+ UNORDERED_AUTO_TEST (test_initializer_list) {
+ boost::unordered_set<int> x1 = {2, 10, 45, -5};
+ BOOST_TEST(x1.find(10) != x1.end());
+ BOOST_TEST(x1.find(46) == x1.end());
+ }
+
+#endif
+}
+
+RUN_TESTS_QUIET()
diff --git a/src/boost/libs/unordered/test/unordered/copy_tests.cpp b/src/boost/libs/unordered/test/unordered/copy_tests.cpp
new file mode 100644
index 000000000..1f1ac8f5a
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/copy_tests.cpp
@@ -0,0 +1,209 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/test.hpp"
+#include "../objects/cxx11_allocator.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/equivalent.hpp"
+#include "../helpers/invariants.hpp"
+
+test::seed_t initialize_seed(9063);
+
+namespace copy_tests {
+
+ template <class T>
+ void copy_construct_tests1(T*, test::random_generator const& generator)
+ {
+ typedef typename T::allocator_type allocator_type;
+
+ typename T::hasher hf;
+ typename T::key_equal eq;
+ typename T::allocator_type al;
+
+ {
+ test::check_instances check_;
+
+ T x;
+ T y(x);
+ BOOST_TEST(y.empty());
+ BOOST_TEST(test::equivalent(y.hash_function(), hf));
+ BOOST_TEST(test::equivalent(y.key_eq(), eq));
+ BOOST_TEST(test::equivalent(y.get_allocator(), al));
+ BOOST_TEST(x.max_load_factor() == y.max_load_factor());
+ BOOST_TEST(test::selected_count(y.get_allocator()) ==
+ (allocator_type::is_select_on_copy));
+ test::check_equivalent_keys(y);
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(1000, generator);
+
+ T x(v.begin(), v.end());
+ T y(x);
+ test::unordered_equivalence_tester<T> equivalent(x);
+ BOOST_TEST(equivalent(y));
+ BOOST_TEST(test::selected_count(y.get_allocator()) ==
+ (allocator_type::is_select_on_copy));
+ test::check_equivalent_keys(y);
+ }
+
+ {
+ test::check_instances check_;
+
+ // In this test I drop the original containers max load factor, so it
+ // is much lower than the load factor. The hash table is not allowed
+ // to rehash, but the destination container should probably allocate
+ // enough buckets to decrease the load factor appropriately.
+ test::random_values<T> v(1000, generator);
+ T x(v.begin(), v.end());
+ x.max_load_factor(x.load_factor() / 4);
+ T y(x);
+ test::unordered_equivalence_tester<T> equivalent(x);
+ BOOST_TEST(equivalent(y));
+ // This isn't guaranteed:
+ BOOST_TEST(y.load_factor() < y.max_load_factor());
+ BOOST_TEST(test::selected_count(y.get_allocator()) ==
+ (allocator_type::is_select_on_copy));
+ test::check_equivalent_keys(y);
+ }
+ }
+
+ template <class T>
+ void copy_construct_tests2(T*, test::random_generator const& generator)
+ {
+ typename T::hasher hf(1);
+ typename T::key_equal eq(1);
+ typename T::allocator_type al(1);
+ typename T::allocator_type al2(2);
+
+ typedef typename T::allocator_type allocator_type;
+
+ {
+ test::check_instances check_;
+
+ T x(10000, hf, eq, al);
+ T y(x);
+ BOOST_TEST(y.empty());
+ BOOST_TEST(test::equivalent(y.hash_function(), hf));
+ BOOST_TEST(test::equivalent(y.key_eq(), eq));
+ BOOST_TEST(test::equivalent(y.get_allocator(), al));
+ BOOST_TEST(x.max_load_factor() == y.max_load_factor());
+ BOOST_TEST(test::selected_count(y.get_allocator()) ==
+ (allocator_type::is_select_on_copy));
+ test::check_equivalent_keys(y);
+ }
+
+ {
+ test::check_instances check_;
+
+ T x(1000, hf, eq, al);
+ T y(x, al2);
+ BOOST_TEST(y.empty());
+ BOOST_TEST(test::equivalent(y.hash_function(), hf));
+ BOOST_TEST(test::equivalent(y.key_eq(), eq));
+ BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+ BOOST_TEST(x.max_load_factor() == y.max_load_factor());
+ BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
+ test::check_equivalent_keys(y);
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(1000, generator);
+
+ T x(v.begin(), v.end(), 0, hf, eq, al);
+ T y(x);
+ test::unordered_equivalence_tester<T> equivalent(x);
+ BOOST_TEST(equivalent(y));
+ test::check_equivalent_keys(y);
+ BOOST_TEST(test::selected_count(y.get_allocator()) ==
+ (allocator_type::is_select_on_copy));
+ BOOST_TEST(test::equivalent(y.get_allocator(), al));
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(500, generator);
+
+ T x(v.begin(), v.end(), 0, hf, eq, al);
+ T y(x, al2);
+ test::unordered_equivalence_tester<T> equivalent(x);
+ BOOST_TEST(equivalent(y));
+ test::check_equivalent_keys(y);
+ BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
+ BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+ }
+ }
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator2<test::object> >* test_multimap;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::select_copy> >*
+ test_set_select_copy;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::select_copy> >*
+ test_multiset_select_copy;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::select_copy> >*
+ test_map_select_copy;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::cxx11_allocator<test::object, test::select_copy> >*
+ test_multimap_select_copy;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_select_copy> >*
+ test_set_no_select_copy;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_select_copy> >*
+ test_multiset_no_select_copy;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_select_copy> >*
+ test_map_no_select_copy;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
+ test_multimap_no_select_copy;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(copy_construct_tests1,
+ ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
+ test_multiset_select_copy)(test_map_select_copy)(
+ test_multimap_select_copy)(test_set_no_select_copy)(
+ test_multiset_no_select_copy)(test_map_no_select_copy)(
+ test_multimap_no_select_copy))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(copy_construct_tests2,
+ ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
+ test_multiset_select_copy)(test_map_select_copy)(
+ test_multimap_select_copy)(test_set_no_select_copy)(
+ test_multiset_no_select_copy)(test_map_no_select_copy)(
+ test_multimap_no_select_copy))(
+ (default_generator)(generate_collisions)(limited_range)))
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/deduction_tests.cpp b/src/boost/libs/unordered/test/unordered/deduction_tests.cpp
new file mode 100644
index 000000000..673c0609e
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/deduction_tests.cpp
@@ -0,0 +1,352 @@
+
+// Copyright 2017-2018 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 <boost/unordered_map.hpp>
+#include <iostream>
+#include <vector>
+
+#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
+struct hash_equals
+{
+ template <typename T> bool operator()(T const& x) const
+ {
+ boost::hash<T> hf;
+ return hf(x);
+ }
+
+ template <typename T> bool operator()(T const& x, T const& y) const
+ {
+ std::equal_to<T> eq;
+ return eq(x, y);
+ }
+};
+
+template <typename T> struct test_allocator
+{
+ typedef T value_type;
+ test_allocator() = default;
+ template <typename T2> test_allocator(test_allocator<T2> const&) {}
+ T* allocate(std::size_t n) const { return (T*)malloc(sizeof(T) * n); }
+ void deallocate(T* ptr, std::size_t) const { free(ptr); }
+ bool operator==(test_allocator const&) { return true; }
+ bool operator!=(test_allocator const&) { return false; }
+};
+#endif
+
+int main()
+{
+ std::cout << "BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES: "
+ << BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES << std::endl;
+
+#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
+ std::vector<std::pair<int, int> > x;
+ x.push_back(std::make_pair(1, 3));
+ x.push_back(std::make_pair(5, 10));
+ test_allocator<std::pair<const int, int> > pair_allocator;
+ hash_equals f;
+
+ // unordered_map
+
+ /*
+ template<class InputIterator,
+ class Hash = hash<iter_key_t<InputIterator>>,
+ class Pred = equal_to<iter_key_t<InputIterator>>,
+ class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+ unordered_map(InputIterator, InputIterator, typename see below::size_type =
+ see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ Hash, Pred,
+ Allocator>;
+ */
+
+ {
+ boost::unordered_map m(x.begin(), x.end());
+ static_assert(
+ std::is_same<decltype(m), boost::unordered_map<int, int> >::value);
+ }
+
+ /* Ambiguous:
+ {
+ boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>());
+ static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
+ std::hash<int>>>::value);
+ }
+
+ {
+ boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>(),
+ std::equal_to<int>());
+ static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
+ std::hash<int>, std::equal_to<int>>>::value);
+ }
+ */
+
+ {
+ boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>(),
+ std::equal_to<int>(), pair_allocator);
+ static_assert(std::is_same<decltype(m),
+ boost::unordered_map<int, int, std::hash<int>, std::equal_to<int>,
+ test_allocator<std::pair<const int, int> > > >::value);
+ }
+
+ /*
+ template<class Key, class T, class Hash = hash<Key>,
+ class Pred = equal_to<Key>, class Allocator = allocator<pair<const
+ Key, T>>>
+ unordered_map(initializer_list<pair<const Key, T>>,
+ typename see below::size_type = see below, Hash = Hash(),
+ Pred = Pred(), Allocator = Allocator())
+ -> unordered_map<Key, T, Hash, Pred, Allocator>;
+ */
+
+ {
+ boost::unordered_map m({std::pair<int const, int>(1, 2)});
+ static_assert(
+ std::is_same<decltype(m), boost::unordered_map<int, int> >::value);
+ }
+
+ /* Ambiguous
+ {
+ boost::unordered_map m({std::pair<int const, int>(1,2)}, 0,
+ std::hash<int>());
+ static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
+ std::hash<int>>>::value);
+ }
+
+ {
+ boost::unordered_map m({std::pair<int const, int>(1,2)}, 0,
+ std::hash<int>(), std::equal_to<int>());
+ static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
+ std::hash<int>, std::equal_to<int>>>::value);
+ }
+ */
+
+ {
+ boost::unordered_map m(
+ {std::pair<int const, int>(1, 2)}, 0, f, f, pair_allocator);
+ static_assert(std::is_same<decltype(m),
+ boost::unordered_map<int, int, hash_equals, hash_equals,
+ test_allocator<std::pair<const int, int> > > >::value);
+ }
+
+ /*
+ template<class InputIterator, class Allocator>
+ unordered_map(InputIterator, InputIterator, typename see below::size_type,
+ Allocator)
+ -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ hash<iter_key_t<InputIterator>>,
+ equal_to<iter_key_t<InputIterator>>,
+ Allocator>;
+ */
+
+ /* Ambiguous
+ {
+ boost::unordered_map m(x.begin(), x.end(), 0u, pair_allocator);
+ static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
+ boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+ */
+
+ /*
+ template<class InputIterator, class Allocator>
+ unordered_map(InputIterator, InputIterator, Allocator)
+ -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ hash<iter_key_t<InputIterator>>,
+ equal_to<iter_key_t<InputIterator>>,
+ Allocator>;
+ */
+
+ /* No constructor:
+ {
+ boost::unordered_map m(x.begin(), x.end(), pair_allocator);
+ static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
+ boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+ */
+
+ /*
+ template<class InputIterator, class Hash, class Allocator>
+ unordered_map(InputIterator, InputIterator, typename see below::size_type,
+ Hash, Allocator)
+ -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ Hash,
+ equal_to<iter_key_t<InputIterator>>, Allocator>;
+ */
+
+ /* Ambiguous
+ {
+ boost::unordered_map m(x.begin(), x.end(), 0u, f, pair_allocator);
+ static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
+ hash_equals, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+ */
+
+ /*
+ template<class Key, class T, typename Allocator>
+ unordered_map(initializer_list<pair<const Key, T>>, typename see
+ below::size_type,
+ Allocator)
+ -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
+ */
+
+ /* Ambiguous
+ {
+ boost::unordered_map m({std::pair<int const, int>(1,2)}, 0, pair_allocator);
+ static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
+ boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+ */
+
+ /*
+ template<class Key, class T, typename Allocator>
+ unordered_map(initializer_list<pair<const Key, T>>, Allocator)
+ -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
+ */
+
+ {
+ boost::unordered_map m({std::pair<int const, int>(1, 2)}, pair_allocator);
+ static_assert(std::is_same<decltype(m),
+ boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
+ test_allocator<std::pair<const int, int> > > >::value);
+ }
+
+ /*
+ template<class Key, class T, class Hash, class Allocator>
+ unordered_map(initializer_list<pair<const Key, T>>, typename see
+ below::size_type, Hash,
+ Allocator)
+ -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
+ */
+
+ /* Ambiguous
+ {
+ boost::unordered_map m({std::pair<int const, int>(1,2)}, 0, f,
+ pair_allocator);
+ static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
+ boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+ */
+
+ // unordered_multimap
+
+ {
+ boost::unordered_multimap m(x.begin(), x.end());
+ static_assert(
+ std::is_same<decltype(m), boost::unordered_multimap<int, int> >::value);
+ }
+
+ /* Ambiguous:
+ {
+ boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>());
+ static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
+ std::hash<int>>>::value);
+ }
+
+ {
+ boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>(),
+ std::equal_to<int>());
+ static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
+ std::hash<int>, std::equal_to<int>>>::value);
+ }
+ */
+
+ {
+ boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>(),
+ std::equal_to<int>(), pair_allocator);
+ static_assert(std::is_same<decltype(m),
+ boost::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>,
+ test_allocator<std::pair<const int, int> > > >::value);
+ }
+
+ {
+ boost::unordered_multimap m({std::pair<int const, int>(1, 2)});
+ static_assert(
+ std::is_same<decltype(m), boost::unordered_multimap<int, int> >::value);
+ }
+
+ /* Ambiguous
+ {
+ boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
+ std::hash<int>());
+ static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
+ std::hash<int>>>::value);
+ }
+
+ {
+ boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
+ std::hash<int>(), std::equal_to<int>());
+ static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
+ std::hash<int>, std::equal_to<int>>>::value);
+ }
+ */
+
+ {
+ boost::unordered_multimap m(
+ {std::pair<int const, int>(1, 2)}, 0, f, f, pair_allocator);
+ static_assert(std::is_same<decltype(m),
+ boost::unordered_multimap<int, int, hash_equals, hash_equals,
+ test_allocator<std::pair<const int, int> > > >::value);
+ }
+
+ /* Ambiguous
+ {
+ boost::unordered_multimap m(x.begin(), x.end(), 0u, pair_allocator);
+ static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
+ boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+ */
+
+ /* No constructor:
+ {
+ boost::unordered_multimap m(x.begin(), x.end(), pair_allocator);
+ static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
+ boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+ */
+
+ /* Ambiguous
+ {
+ boost::unordered_multimap m(x.begin(), x.end(), 0u, f, pair_allocator);
+ static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
+ hash_equals, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+
+ {
+ boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
+ pair_allocator);
+ static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
+ boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
+ int>>>>::value);
+ }
+ */
+
+ {
+ boost::unordered_multimap m(
+ {std::pair<int const, int>(1, 2)}, pair_allocator);
+ static_assert(std::is_same<decltype(m),
+ boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
+ test_allocator<std::pair<const int, int> > > >::value);
+ }
+
+/* Ambiguous
+{
+ boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0, f,
+pair_allocator);
+ static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
+boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
+int>>>>::value);
+}
+*/
+
+#endif
+}
diff --git a/src/boost/libs/unordered/test/unordered/detail_tests.cpp b/src/boost/libs/unordered/test/unordered/detail_tests.cpp
new file mode 100644
index 000000000..545c83813
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/detail_tests.cpp
@@ -0,0 +1,101 @@
+
+// Copyright 2017 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include <map>
+
+// Pretty inefficient, but the test is fast enough.
+// Might be too slow if we had larger primes?
+bool is_prime(std::size_t x)
+{
+ if (x == 2) {
+ return true;
+ } else if (x == 1 || x % 2 == 0) {
+ return false;
+ } else {
+ // y*y <= x had rounding errors, so instead use y <= (x/y).
+ for (std::size_t y = 3; y <= (x / y); y += 2) {
+ if (x % y == 0) {
+ return false;
+ break;
+ }
+ }
+
+ return true;
+ }
+}
+
+void test_next_prime(std::size_t value)
+{
+ std::size_t x = boost::unordered::detail::next_prime(value);
+ BOOST_TEST(is_prime(x));
+ BOOST_TEST(x >= value);
+}
+
+void test_prev_prime(std::size_t value)
+{
+ std::size_t x = boost::unordered::detail::prev_prime(value);
+ BOOST_TEST(is_prime(x));
+ BOOST_TEST(x <= value);
+ if (x > value) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << x << "," << value << std::endl;
+ }
+}
+
+UNORDERED_AUTO_TEST (next_prime_test) {
+ BOOST_TEST(!is_prime(0));
+ BOOST_TEST(!is_prime(1));
+ BOOST_TEST(is_prime(2));
+ BOOST_TEST(is_prime(3));
+ BOOST_TEST(is_prime(13));
+ BOOST_TEST(!is_prime(4));
+ BOOST_TEST(!is_prime(100));
+
+ BOOST_TEST(boost::unordered::detail::next_prime(0) > 0);
+
+ // test_prev_prime doesn't work for values less than 17.
+ // Which should be okay, unless an allocator has a really tiny
+ // max_size?
+ const std::size_t min_prime = 17;
+
+ // test_next_prime doesn't work for values greater than this,
+ // which might be a problem if you've got terrabytes of memory?
+ // I seriously doubt the container would work well at such sizes
+ // regardless.
+ const std::size_t max_prime = 4294967291ul;
+
+ std::size_t i;
+
+ BOOST_TEST(is_prime(min_prime));
+ BOOST_TEST(is_prime(max_prime));
+
+ for (i = 0; i < 10000; ++i) {
+ if (i < min_prime) {
+ BOOST_TEST(boost::unordered::detail::prev_prime(i) == min_prime);
+ } else {
+ test_prev_prime(i);
+ }
+ test_next_prime(i);
+ }
+
+ std::size_t last = i - 1;
+ for (; i > last; last = i, i += i / 5) {
+ if (i > max_prime) {
+ BOOST_TEST(boost::unordered::detail::next_prime(i) == max_prime);
+ } else {
+ test_next_prime(i);
+ }
+ test_prev_prime(i);
+ }
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/emplace_tests.cpp b/src/boost/libs/unordered/test/unordered/emplace_tests.cpp
new file mode 100644
index 000000000..b424d3d7a
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/emplace_tests.cpp
@@ -0,0 +1,514 @@
+//
+// 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include <boost/functional/hash/hash.hpp>
+#include "../helpers/test.hpp"
+#include "../helpers/count.hpp"
+#include <string>
+
+// 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<emplace_value, boost::hash<emplace_value> >
+ container;
+ typedef container::iterator iterator;
+ typedef std::pair<iterator, bool> 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<emplace_value,
+ boost::hash<emplace_value> >
+ 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<emplace_value, emplace_value,
+ boost::hash<emplace_value> >
+ container;
+ typedef container::iterator iterator;
+ typedef std::pair<iterator, bool> 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<emplace_value, emplace_value,
+ boost::hash<emplace_value> >
+ 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);
+ }
+
+ UNORDERED_AUTO_TEST (try_emplace) {
+ test::check_instances check_;
+
+ typedef boost::unordered_map<int, emplace_value> container;
+ typedef container::iterator iterator;
+ typedef std::pair<iterator, bool> return_type;
+ container x(10);
+ return_type r1, r2, r3;
+
+ int k1 = 3;
+ emplace_value m1(414, "grr");
+ r1 = x.try_emplace(3, 414, "grr");
+ BOOST_TEST(r1.second);
+ BOOST_TEST(r1.first->first == k1);
+ BOOST_TEST(r1.first->second == m1);
+ BOOST_TEST_EQ(x.size(), 1u);
+ BOOST_TEST_EQ(check_.instances(), 2);
+ BOOST_TEST_EQ(check_.constructions(), 2);
+
+ int k2 = 10;
+ emplace_value m2(25, "", 'z');
+ r2 = x.try_emplace(10, 25, std::string(""), 'z');
+ BOOST_TEST(r2.second);
+ BOOST_TEST(r2.first->first == k2);
+ BOOST_TEST(r2.first->second == m2);
+ BOOST_TEST_EQ(x.size(), 2u);
+ BOOST_TEST_EQ(check_.instances(), 4);
+ BOOST_TEST_EQ(check_.constructions(), 4);
+
+ BOOST_TEST(x.find(k1)->second == m1);
+ BOOST_TEST(x.find(k2)->second == m2);
+
+ r3 = x.try_emplace(k2, 68, "jfeoj", 'p', 49309, 2323);
+ BOOST_TEST(!r3.second);
+ BOOST_TEST(r3.first == r2.first);
+ BOOST_TEST(r3.first->second == m2);
+ BOOST_TEST_EQ(x.size(), 2u);
+ BOOST_TEST_EQ(check_.instances(), 4);
+ BOOST_TEST_EQ(check_.constructions(), 4);
+
+ BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 808709, "what"));
+ BOOST_TEST(
+ r2.first ==
+ x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10));
+ BOOST_TEST(r2.first->second == m2);
+ BOOST_TEST_EQ(x.size(), 2u);
+ }
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/equality_tests.cpp b/src/boost/libs/unordered/test/unordered/equality_tests.cpp
new file mode 100644
index 000000000..b1029af40
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/equality_tests.cpp
@@ -0,0 +1,156 @@
+
+// Copyright 2008-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include <boost/preprocessor/seq.hpp>
+#include <list>
+#include "../helpers/test.hpp"
+
+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; }
+
+ std::size_t operator()(int x) const
+ {
+ return alt_hash_ ? static_cast<std::size_t>(x % 250)
+ : static_cast<std::size_t>((x + 5) % 250);
+ }
+ };
+
+#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
+ { \
+ boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
+ BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
+ BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
+ BOOST_TEST(set1 op set2); \
+ }
+
+#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
+ { \
+ boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \
+ BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
+ BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
+ BOOST_TEST(set1 op set2); \
+ }
+
+#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
+ { \
+ boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \
+ BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
+ BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
+ BOOST_TEST(map1 op map2); \
+ }
+
+#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
+ { \
+ boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, map2; \
+ BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
+ BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
+ BOOST_TEST(map1 op map2); \
+ }
+
+#define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
+#define UNORDERED_MAP_INSERT(r, map, item) \
+ map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
+
+ UNORDERED_AUTO_TEST (equality_size_tests) {
+ boost::unordered_set<int> x1, x2;
+ BOOST_TEST(x1 == x2);
+ BOOST_TEST(!(x1 != x2));
+
+ x1.insert(1);
+ BOOST_TEST(x1 != x2);
+ BOOST_TEST(!(x1 == x2));
+ BOOST_TEST(x2 != x1);
+ BOOST_TEST(!(x2 == x1));
+
+ x2.insert(1);
+ BOOST_TEST(x1 == x2);
+ BOOST_TEST(!(x1 != x2));
+
+ x2.insert(2);
+ BOOST_TEST(x1 != x2);
+ BOOST_TEST(!(x1 == x2));
+ BOOST_TEST(x2 != x1);
+ BOOST_TEST(!(x2 == x1));
+ }
+
+ UNORDERED_AUTO_TEST (equality_key_value_tests) {
+ UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2))
+ UNORDERED_EQUALITY_SET_TEST((2), ==, (2))
+ UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1)))
+ }
+
+ UNORDERED_AUTO_TEST (equality_collision_test) {
+ UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (501))
+ UNORDERED_EQUALITY_MULTISET_TEST((1)(251), !=, (1)(501))
+ UNORDERED_EQUALITY_MULTIMAP_TEST(((251)(1))((1)(1)), !=, ((501)(1))((1)(1)))
+ UNORDERED_EQUALITY_MULTISET_TEST((1)(501), ==, (1)(501))
+ UNORDERED_EQUALITY_SET_TEST((1)(501), ==, (501)(1))
+ }
+
+ UNORDERED_AUTO_TEST (equality_group_size_test) {
+ UNORDERED_EQUALITY_MULTISET_TEST((10)(20)(20), !=, (10)(10)(20))
+ UNORDERED_EQUALITY_MULTIMAP_TEST(
+ ((10)(1))((20)(1))((20)(1)), !=, ((10)(1))((20)(1))((10)(1)))
+ UNORDERED_EQUALITY_MULTIMAP_TEST(
+ ((20)(1))((10)(1))((10)(1)), ==, ((10)(1))((20)(1))((10)(1)))
+ }
+
+ UNORDERED_AUTO_TEST (equality_map_value_test) {
+ UNORDERED_EQUALITY_MAP_TEST(((1)(1)), !=, ((1)(2)))
+ UNORDERED_EQUALITY_MAP_TEST(((1)(1)), ==, ((1)(1)))
+ UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1)), !=, ((1)(2)))
+ UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
+ UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
+ UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
+ }
+
+ UNORDERED_AUTO_TEST (equality_predicate_test) {
+ UNORDERED_EQUALITY_SET_TEST((1), !=, (1001))
+ UNORDERED_EQUALITY_MAP_TEST(((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
+ }
+
+ UNORDERED_AUTO_TEST (equality_multiple_group_test) {
+ UNORDERED_EQUALITY_MULTISET_TEST(
+ (1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
+ (3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(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_TEST(set1 == set2);
+ set1.insert(1);
+ set2.insert(2);
+ BOOST_TEST(set1 != set2);
+ set1.insert(2);
+ set2.insert(1);
+ BOOST_TEST(set1 == set2);
+ set1.insert(10);
+ set2.insert(20);
+ BOOST_TEST(set1 != set2);
+ set1.insert(20);
+ set2.insert(10);
+ BOOST_TEST(set1 == set2);
+ }
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/equivalent_keys_tests.cpp b/src/boost/libs/unordered/test/unordered/equivalent_keys_tests.cpp
new file mode 100644
index 000000000..f040819db
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/equivalent_keys_tests.cpp
@@ -0,0 +1,77 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include <algorithm>
+#include <map>
+#include "../helpers/list.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/invariants.hpp"
+
+template <class Container, class Iterator>
+void test_equal_insertion(Iterator begin, Iterator end)
+{
+ typedef test::ordered<Container> tracker;
+
+ Container x1;
+ tracker x2 = test::create_ordered(x1);
+
+ for (Iterator it = begin; it != end; ++it) {
+ x1.insert(*it);
+ x2.insert(*it);
+ x2.compare_key(x1, *it);
+ }
+
+ x2.compare(x1);
+ test::check_equivalent_keys(x1);
+}
+
+UNORDERED_AUTO_TEST (set_tests) {
+ int values[][5] = {{1}, {54, 23}, {-13, 65}, {77, 77}, {986, 25, 986}};
+
+ typedef boost::unordered_set<int> set;
+ typedef boost::unordered_multiset<int> multiset;
+
+ test_equal_insertion<set>(values[0], values[0] + 1);
+ test_equal_insertion<set>(values[1], values[1] + 2);
+ test_equal_insertion<set>(values[2], values[2] + 2);
+ test_equal_insertion<set>(values[3], values[3] + 2);
+ test_equal_insertion<set>(values[4], values[4] + 3);
+
+ test_equal_insertion<multiset>(values[0], values[0] + 1);
+ test_equal_insertion<multiset>(values[1], values[1] + 2);
+ test_equal_insertion<multiset>(values[2], values[2] + 2);
+ test_equal_insertion<multiset>(values[3], values[3] + 2);
+ test_equal_insertion<multiset>(values[4], values[4] + 3);
+}
+
+UNORDERED_AUTO_TEST (map_tests) {
+ typedef test::list<std::pair<int const, int> > values_type;
+ values_type v[5];
+ v[0].push_back(std::pair<int const, int>(1, 1));
+ v[1].push_back(std::pair<int const, int>(28, 34));
+ v[1].push_back(std::pair<int const, int>(16, 58));
+ v[1].push_back(std::pair<int const, int>(-124, 62));
+ v[2].push_back(std::pair<int const, int>(432, 12));
+ v[2].push_back(std::pair<int const, int>(9, 13));
+ v[2].push_back(std::pair<int const, int>(432, 24));
+
+ for (int i = 0; i < 5; ++i)
+ test_equal_insertion<boost::unordered_map<int, int> >(
+ v[i].begin(), v[i].end());
+
+ for (int i2 = 0; i2 < 5; ++i2)
+ test_equal_insertion<boost::unordered_multimap<int, int> >(
+ v[i2].begin(), v[i2].end());
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/erase_equiv_tests.cpp b/src/boost/libs/unordered/test/unordered/erase_equiv_tests.cpp
new file mode 100644
index 000000000..effe0cd54
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/erase_equiv_tests.cpp
@@ -0,0 +1,217 @@
+
+// Copyright 2006-2009 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)
+
+// The code for erasing elements from containers with equivalent keys is very
+// hairy with several tricky edge cases - so explicitly test each one.
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../helpers/list.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/helpers.hpp"
+#include <set>
+#include <iterator>
+#include "../objects/test.hpp"
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
+#pragma warning(disable : 4267) // conversion from 'size_t' to 'unsigned int',
+ // possible loss of data.
+#endif
+
+struct write_pair_type
+{
+ template <class X1, class X2>
+ void operator()(std::pair<X1, X2> const& x) const
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "(" << x.first << "," << x.second << ")";
+ }
+} write_pair;
+
+template <class Container> void write_container(Container const& x)
+{
+ std::for_each(x.begin(), x.end(), write_pair);
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
+}
+
+// Make everything collide - for testing erase in a single bucket.
+struct collision_hash
+{
+ std::size_t operator()(int) const { return 0; }
+};
+
+// For testing erase in 2 buckets.
+struct collision2_hash
+{
+ std::size_t operator()(int x) const
+ {
+ return static_cast<std::size_t>(x & 1);
+ }
+};
+
+// For testing erase in lots of buckets.
+struct collision3_hash
+{
+ std::size_t operator()(int x) const { return static_cast<std::size_t>(x); }
+};
+
+typedef boost::unordered_multimap<int, int, collision_hash, std::equal_to<int>,
+ test::allocator1<std::pair<int const, int> > >
+ collide_map;
+typedef boost::unordered_multimap<int, int, collision2_hash, std::equal_to<int>,
+ test::allocator2<std::pair<int const, int> > >
+ collide_map2;
+typedef boost::unordered_multimap<int, int, collision3_hash, std::equal_to<int>,
+ test::allocator2<std::pair<int const, int> > >
+ collide_map3;
+typedef collide_map::value_type collide_value;
+typedef test::list<collide_value> collide_list;
+
+UNORDERED_AUTO_TEST (empty_range_tests) {
+ collide_map x;
+ x.erase(x.begin(), x.end());
+ x.erase(x.begin(), x.begin());
+ x.erase(x.end(), x.end());
+ test::check_equivalent_keys(x);
+}
+
+UNORDERED_AUTO_TEST (single_item_tests) {
+ collide_list init;
+ init.push_back(collide_value(1, 1));
+
+ collide_map x(init.begin(), init.end());
+ x.erase(x.begin(), x.begin());
+ BOOST_TEST(x.count(1) == 1 && x.size() == 1);
+ test::check_equivalent_keys(x);
+ x.erase(x.end(), x.end());
+ BOOST_TEST(x.count(1) == 1 && x.size() == 1);
+ test::check_equivalent_keys(x);
+ x.erase(x.begin(), x.end());
+ BOOST_TEST(x.count(1) == 0 && x.size() == 0);
+ test::check_equivalent_keys(x);
+}
+
+UNORDERED_AUTO_TEST (two_equivalent_item_tests) {
+ collide_list init;
+ init.push_back(collide_value(1, 1));
+ init.push_back(collide_value(1, 2));
+
+ {
+ collide_map x(init.begin(), init.end());
+ x.erase(x.begin(), x.end());
+ BOOST_TEST(x.count(1) == 0 && x.size() == 0);
+ test::check_equivalent_keys(x);
+ }
+
+ {
+ collide_map x(init.begin(), init.end());
+ int value = test::next(x.begin())->second;
+ x.erase(x.begin(), test::next(x.begin()));
+ BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
+ x.begin()->second == value);
+ test::check_equivalent_keys(x);
+ }
+
+ {
+ collide_map x(init.begin(), init.end());
+ int value = x.begin()->second;
+ x.erase(test::next(x.begin()), x.end());
+ BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
+ x.begin()->second == value);
+ test::check_equivalent_keys(x);
+ }
+}
+
+// More automated tests...
+
+template <class Range1, class Range2>
+bool compare(Range1 const& x, Range2 const& y)
+{
+ collide_list a(x.begin(), x.end());
+ collide_list b(y.begin(), y.end());
+ a.sort();
+ b.sort();
+ return a == b;
+}
+
+template <class Container>
+bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
+{
+ collide_list l(x.begin(), x.end());
+
+ l.erase(test::next(l.begin(), start), test::next(l.begin(), end));
+ x.erase(test::next(x.begin(), start), test::next(x.begin(), end));
+
+ test::check_equivalent_keys(x);
+ return compare(l, x);
+}
+
+template <class Container> void erase_subrange_tests(Container const& x)
+{
+ for (std::size_t length = 0; length < x.size(); ++length) {
+ for (std::size_t position = 0; position < x.size() - length; ++position) {
+ Container y(x);
+ collide_list init(y.begin(), y.end());
+ if (!general_erase_range_test(y, position, position + length)) {
+ BOOST_ERROR("general_erase_range_test failed.");
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase: [" << position << ","
+ << position + length << ")\n";
+ write_container(init);
+ write_container(y);
+ }
+ }
+ }
+}
+
+template <class Container>
+void x_by_y_erase_range_tests(Container*, int values, int duplicates)
+{
+ Container y;
+
+ for (int i = 0; i < values; ++i) {
+ for (int j = 0; j < duplicates; ++j) {
+ y.insert(collide_value(i, j));
+ }
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Values: " << values
+ << ", Duplicates: " << duplicates << "\n";
+ erase_subrange_tests(y);
+}
+
+template <class Container>
+void exhaustive_erase_tests(Container* x, int num_values, int num_duplicated)
+{
+ for (int i = 0; i < num_values; ++i) {
+ for (int j = 0; j < num_duplicated; ++j) {
+ x_by_y_erase_range_tests(x, i, j);
+ }
+ }
+}
+
+UNORDERED_AUTO_TEST (exhaustive_collide_tests) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide_tests:\n";
+ collide_map m;
+ exhaustive_erase_tests((collide_map*)0, 4, 4);
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
+}
+
+UNORDERED_AUTO_TEST (exhaustive_collide2_tests) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide2_tests:\n";
+ exhaustive_erase_tests((collide_map2*)0, 8, 4);
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
+}
+
+UNORDERED_AUTO_TEST (exhaustive_collide3_tests) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide3_tests:\n";
+ exhaustive_erase_tests((collide_map3*)0, 8, 4);
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/erase_tests.cpp b/src/boost/libs/unordered/test/unordered/erase_tests.cpp
new file mode 100644
index 000000000..fecb7dc0a
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/erase_tests.cpp
@@ -0,0 +1,267 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/test.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/equivalent.hpp"
+#include "../helpers/helpers.hpp"
+#include "../helpers/invariants.hpp"
+#include <vector>
+#include <cstdlib>
+
+namespace erase_tests {
+
+ test::seed_t initialize_seed(85638);
+
+ template <class Container>
+ void erase_tests1(Container*, test::random_generator generator)
+ {
+ typedef typename Container::iterator iterator;
+ typedef typename Container::const_iterator c_iterator;
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(1000, generator);
+ Container x(v.begin(), v.end());
+ int iterations = 0;
+ for (typename test::random_values<Container>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ std::size_t count = x.count(test::get_key<Container>(*it));
+ std::size_t old_size = x.size();
+ BOOST_TEST(count == x.erase(test::get_key<Container>(*it)));
+ BOOST_TEST(x.size() == old_size - count);
+ BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
+ BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
+ if (++iterations % 20 == 0)
+ test::check_equivalent_keys(x);
+ }
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(begin()).\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(1000, generator);
+ Container x(v.begin(), v.end());
+ std::size_t size = x.size();
+ int iterations = 0;
+ while (size > 0 && !x.empty()) {
+ typename Container::key_type key = test::get_key<Container>(*x.begin());
+ std::size_t count = x.count(key);
+ iterator pos = x.erase(x.begin());
+ --size;
+ BOOST_TEST(pos == x.begin());
+ BOOST_TEST(x.count(key) == count - 1);
+ BOOST_TEST(x.size() == size);
+ if (++iterations % 20 == 0)
+ test::check_equivalent_keys(x);
+ }
+ BOOST_TEST(x.empty());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random position).\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(1000, generator);
+ Container x(v.begin(), v.end());
+ std::size_t size = x.size();
+ int iterations = 0;
+ while (size > 0 && !x.empty()) {
+ std::size_t index = test::random_value(x.size());
+ c_iterator prev, pos, next;
+ if (index == 0) {
+ prev = pos = x.begin();
+ } else {
+ prev = test::next(x.begin(), index - 1);
+ pos = test::next(prev);
+ }
+ next = test::next(pos);
+ typename Container::key_type key = test::get_key<Container>(*pos);
+ std::size_t count = x.count(key);
+ BOOST_TEST(count > 0);
+ BOOST_TEST(next == x.erase(pos));
+ --size;
+ if (size > 0)
+ BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
+ BOOST_TEST(x.count(key) == count - 1);
+ if (x.count(key) != count - 1) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
+ << std::endl;
+ }
+ BOOST_TEST(x.size() == size);
+ if (++iterations % 20 == 0)
+ test::check_equivalent_keys(x);
+ }
+ BOOST_TEST(x.empty());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(ranges).\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(500, generator);
+ Container x(v.begin(), v.end());
+
+ std::size_t size = x.size();
+
+ // I'm actually stretching it a little here, as the standard says it
+ // returns 'the iterator immediately following the erase elements'
+ // and if nothing is erased, then there's nothing to follow. But I
+ // think this is the only sensible option...
+ BOOST_TEST(x.erase(x.end(), x.end()) == x.end());
+ BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin());
+ BOOST_TEST(x.size() == size);
+ test::check_equivalent_keys(x);
+
+ BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.begin() == x.end());
+ test::check_equivalent_keys(x);
+
+ BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
+ test::check_equivalent_keys(x);
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random ranges).\n";
+ {
+ test::check_instances check_;
+ Container x;
+
+ for (int i = 0; i < 100; ++i) {
+ test::random_values<Container> v(1000, generator);
+ x.insert(v.begin(), v.end());
+
+ // Note that erase only invalidates the erased iterators.
+ std::vector<c_iterator> iterators;
+ for (c_iterator it = x.cbegin(); it != x.cend(); ++it) {
+ iterators.push_back(it);
+ }
+ iterators.push_back(x.cend());
+
+ while (iterators.size() > 1) {
+ std::size_t start = test::random_value(iterators.size());
+ std::size_t length = test::random_value(iterators.size() - start);
+ x.erase(iterators[start], iterators[start + length]);
+ iterators.erase(test::next(iterators.begin(), start),
+ test::next(iterators.begin(), start + length));
+
+ BOOST_TEST(x.size() == iterators.size() - 1);
+ typename std::vector<c_iterator>::const_iterator i2 =
+ iterators.begin();
+ for (c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
+ BOOST_TEST(i1 == *i2);
+ ++i2;
+ }
+ BOOST_TEST(x.cend() == *i2);
+
+ test::check_equivalent_keys(x);
+ }
+ BOOST_TEST(x.empty());
+ }
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(begin()).\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(1000, generator);
+ Container x(v.begin(), v.end());
+ std::size_t size = x.size();
+ int iterations = 0;
+ while (size > 0 && !x.empty()) {
+ typename Container::key_type key = test::get_key<Container>(*x.begin());
+ std::size_t count = x.count(key);
+ x.quick_erase(x.begin());
+ --size;
+ BOOST_TEST(x.count(key) == count - 1);
+ BOOST_TEST(x.size() == size);
+ if (++iterations % 20 == 0)
+ test::check_equivalent_keys(x);
+ }
+ BOOST_TEST(x.empty());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(random position).\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(1000, generator);
+ Container x(v.begin(), v.end());
+ std::size_t size = x.size();
+ int iterations = 0;
+ while (size > 0 && !x.empty()) {
+ std::size_t index = test::random_value(x.size());
+ typename Container::const_iterator prev, pos, next;
+ if (index == 0) {
+ prev = pos = x.begin();
+ } else {
+ prev = test::next(x.begin(), index - 1);
+ pos = test::next(prev);
+ }
+ next = test::next(pos);
+ typename Container::key_type key = test::get_key<Container>(*pos);
+ std::size_t count = x.count(key);
+ BOOST_TEST(count > 0);
+ x.quick_erase(pos);
+ --size;
+ if (size > 0)
+ BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
+ BOOST_TEST(x.count(key) == count - 1);
+ if (x.count(key) != count - 1) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
+ << std::endl;
+ }
+ BOOST_TEST(x.size() == size);
+ if (++iterations % 20 == 0)
+ test::check_equivalent_keys(x);
+ }
+ BOOST_TEST(x.empty());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "clear().\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(500, generator);
+ Container x(v.begin(), v.end());
+ x.clear();
+ BOOST_TEST(x.empty());
+ BOOST_TEST(x.begin() == x.end());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
+ }
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator2<test::object> >* test_multimap;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(
+ erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/extract_tests.cpp b/src/boost/libs/unordered/test/unordered/extract_tests.cpp
new file mode 100644
index 000000000..143387386
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/extract_tests.cpp
@@ -0,0 +1,133 @@
+
+// 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/equivalent.hpp"
+#include "../helpers/helpers.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/test.hpp"
+#include "../helpers/tracker.hpp"
+#include "../objects/test.hpp"
+
+namespace extract_tests {
+
+ test::seed_t initialize_seed(85638);
+
+ template <class Container>
+ void extract_tests1(Container*, test::random_generator generator)
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Extract by key.\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(1000, generator);
+ Container x(v.begin(), v.end());
+ int iterations = 0;
+ for (typename test::random_values<Container>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ std::size_t count = x.count(test::get_key<Container>(*it));
+ std::size_t old_size = x.size();
+ std::size_t new_count = count ? count - 1 : count;
+ std::size_t new_size = count ? old_size - 1 : old_size;
+ typename Container::node_type n =
+ x.extract(test::get_key<Container>(*it));
+ BOOST_TEST((n ? true : false) == (count ? true : false));
+ BOOST_TEST(x.size() == new_size);
+ BOOST_TEST(x.count(test::get_key<Container>(*it)) == new_count);
+ if (!new_count) {
+ BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
+ } else {
+ BOOST_TEST(x.find(test::get_key<Container>(*it)) != x.end());
+ }
+ if (++iterations % 20 == 0)
+ test::check_equivalent_keys(x);
+ }
+ BOOST_TEST(x.empty());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(begin()).\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(1000, generator);
+ Container x(v.begin(), v.end());
+ std::size_t size = x.size();
+ int iterations = 0;
+ while (size > 0 && !x.empty()) {
+ typename Container::key_type key = test::get_key<Container>(*x.begin());
+ std::size_t count = x.count(key);
+ typename Container::node_type n = x.extract(x.begin());
+ BOOST_TEST(n);
+ --size;
+ BOOST_TEST(x.count(key) == count - 1);
+ BOOST_TEST(x.size() == size);
+ if (++iterations % 20 == 0)
+ test::check_equivalent_keys(x);
+ }
+ BOOST_TEST(x.empty());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(random position).\n";
+ {
+ test::check_instances check_;
+
+ test::random_values<Container> v(1000, generator);
+ Container x(v.begin(), v.end());
+ std::size_t size = x.size();
+ int iterations = 0;
+ while (size > 0 && !x.empty()) {
+ using namespace std;
+ int index = rand() % (int)x.size();
+ typename Container::const_iterator prev, pos, next;
+ if (index == 0) {
+ prev = pos = x.begin();
+ } else {
+ prev = test::next(x.begin(), index - 1);
+ pos = test::next(prev);
+ }
+ next = test::next(pos);
+ typename Container::key_type key = test::get_key<Container>(*pos);
+ std::size_t count = x.count(key);
+ typename Container::node_type n = x.extract(pos);
+ BOOST_TEST(n);
+ --size;
+ if (size > 0)
+ BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
+ BOOST_TEST(x.count(key) == count - 1);
+ BOOST_TEST(x.size() == size);
+ if (++iterations % 20 == 0)
+ test::check_equivalent_keys(x);
+ }
+ BOOST_TEST(x.empty());
+ }
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
+ }
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator2<test::object> >* test_multimap;
+
+ using test::default_generator;
+ using test::generate_collisions;
+
+ UNORDERED_TEST(
+ extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)))
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/find_tests.cpp b/src/boost/libs/unordered/test/unordered/find_tests.cpp
new file mode 100644
index 000000000..031371c32
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/find_tests.cpp
@@ -0,0 +1,157 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/test.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/helpers.hpp"
+
+namespace find_tests {
+
+ test::seed_t initialize_seed(78937);
+
+ template <class X> void find_tests1(X*, test::random_generator generator)
+ {
+ typedef typename X::iterator iterator;
+
+ {
+ test::check_instances check_;
+
+ test::random_values<X> v(500, generator);
+ X x(v.begin(), v.end());
+ X const& x_const = x;
+ test::ordered<X> tracker = test::create_ordered(x);
+ tracker.insert_range(v.begin(), v.end());
+
+ for (typename test::ordered<X>::const_iterator it1 = tracker.begin();
+ it1 != tracker.end(); ++it1) {
+ typename X::key_type key = test::get_key<X>(*it1);
+ typename X::const_iterator const_pos = x_const.find(key);
+ iterator pos = x.find(key);
+ BOOST_TEST(const_pos != x_const.end());
+ BOOST_TEST(const_pos != x_const.end() &&
+ x_const.key_eq()(key, test::get_key<X>(*const_pos)));
+ BOOST_TEST(pos != x.end());
+ BOOST_TEST(pos != x.end() && x.key_eq()(key, test::get_key<X>(*pos)));
+
+ BOOST_TEST(x.count(key) == tracker.count(key));
+
+ test::compare_pairs(x.equal_range(key), tracker.equal_range(key),
+ (typename X::value_type*)0);
+ test::compare_pairs(x_const.equal_range(key), tracker.equal_range(key),
+ (typename X::value_type*)0);
+ }
+
+ test::random_values<X> v2(500, generator);
+ for (typename test::random_values<X>::const_iterator it2 = v2.begin();
+ it2 != v2.end(); ++it2) {
+ typename X::key_type key = test::get_key<X>(*it2);
+ if (tracker.find(test::get_key<X>(key)) == tracker.end()) {
+ BOOST_TEST(x.find(key) == x.end());
+ BOOST_TEST(x_const.find(key) == x_const.end());
+ BOOST_TEST(x.count(key) == 0);
+ std::pair<iterator, iterator> range = x.equal_range(key);
+ BOOST_TEST(range.first == range.second);
+ }
+ }
+ }
+
+ {
+ test::check_instances check_;
+
+ X x;
+
+ test::random_values<X> v2(5, generator);
+ for (typename test::random_values<X>::const_iterator it3 = v2.begin();
+ it3 != v2.end(); ++it3) {
+ typename X::key_type key = test::get_key<X>(*it3);
+ BOOST_TEST(x.find(key) == x.end());
+ BOOST_TEST(x.count(key) == 0);
+ std::pair<iterator, iterator> range = x.equal_range(key);
+ BOOST_TEST(range.first == range.second);
+ }
+ }
+ }
+
+ struct compatible_key
+ {
+ test::object o_;
+
+ compatible_key(test::object const& o) : o_(o) {}
+ };
+
+ struct compatible_hash
+ {
+ test::hash hash_;
+
+ std::size_t operator()(compatible_key const& k) const
+ {
+ return hash_(k.o_);
+ }
+ };
+
+ struct compatible_predicate
+ {
+ test::equal_to equal_;
+
+ bool operator()(compatible_key const& k1, compatible_key const& k2) const
+ {
+ return equal_(k1.o_, k2.o_);
+ }
+ };
+
+ template <class X>
+ void find_compatible_keys_test(X*, test::random_generator generator)
+ {
+ typedef typename test::random_values<X>::iterator value_iterator;
+ test::random_values<X> v(500, generator);
+ X x(v.begin(), v.end());
+
+ compatible_hash h;
+ compatible_predicate eq;
+
+ for (value_iterator it = v.begin(), end = v.end(); it != end; ++it) {
+ typename X::key_type key = test::get_key<X>(*it);
+ BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
+ }
+
+ test::random_values<X> v2(20, generator);
+
+ for (value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) {
+ typename X::key_type key = test::get_key<X>(*it);
+ BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
+ }
+ }
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator1<test::object> >* test_multimap;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(
+ find_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+ UNORDERED_TEST(find_compatible_keys_test,
+ ((test_set)(test_multiset)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/fwd_map_test.cpp b/src/boost/libs/unordered/test/unordered/fwd_map_test.cpp
new file mode 100644
index 000000000..0c7df04fd
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/fwd_map_test.cpp
@@ -0,0 +1,81 @@
+
+// Copyright 2008-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered/unordered_map_fwd.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+template <typename T>
+void call_swap(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
+{
+ swap(x, y);
+}
+
+template <typename T>
+bool call_equals(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
+{
+ return x == y;
+}
+
+template <typename T>
+bool call_not_equals(
+ boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
+{
+ return x != y;
+}
+
+template <typename T>
+void call_swap(
+ boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
+{
+ swap(x, y);
+}
+
+template <typename T>
+bool call_equals(
+ boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
+{
+ return x == y;
+}
+
+template <typename T>
+bool call_not_equals(
+ boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
+{
+ return x != y;
+}
+
+#include <boost/unordered_map.hpp>
+#include "../helpers/test.hpp"
+
+typedef boost::unordered_map<int, int> int_map;
+typedef boost::unordered_multimap<int, int> int_multimap;
+
+UNORDERED_AUTO_TEST (use_map_fwd_declared_function) {
+ int_map x, y;
+ x[1] = 2;
+ y[2] = 1;
+ call_swap(x, y);
+
+ BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
+ BOOST_TEST(y.find(2) == y.end());
+
+ BOOST_TEST(x.find(1) == x.end());
+ BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
+
+ BOOST_TEST(!call_equals(x, y));
+ BOOST_TEST(call_not_equals(x, y));
+}
+
+UNORDERED_AUTO_TEST (use_multimap_fwd_declared_function) {
+ int_multimap x, y;
+ call_swap(x, y);
+ BOOST_TEST(call_equals(x, y));
+ BOOST_TEST(!call_not_equals(x, y));
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/fwd_set_test.cpp b/src/boost/libs/unordered/test/unordered/fwd_set_test.cpp
new file mode 100644
index 000000000..6512522a8
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/fwd_set_test.cpp
@@ -0,0 +1,106 @@
+
+// Copyright 2008-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered/unordered_set_fwd.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+struct true_type
+{
+ char x[100];
+};
+struct false_type
+{
+ char x;
+};
+
+false_type is_unordered_set_impl(void*);
+
+template <class Value, class Hash, class Pred, class Alloc>
+true_type is_unordered_set_impl(
+ boost::unordered_set<Value, Hash, Pred, Alloc>*);
+
+template <typename T>
+void call_swap(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
+{
+ swap(x, y);
+}
+
+template <typename T>
+bool call_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
+{
+ return x == y;
+}
+
+template <typename T>
+bool call_not_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
+{
+ return x != y;
+}
+
+template <typename T>
+void call_swap(boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
+{
+ swap(x, y);
+}
+
+template <typename T>
+bool call_equals(
+ boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
+{
+ return x == y;
+}
+
+template <typename T>
+bool call_not_equals(
+ boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
+{
+ return x != y;
+}
+
+#include "../helpers/test.hpp"
+
+typedef boost::unordered_set<int> int_set;
+typedef boost::unordered_multiset<int> int_multiset;
+
+UNORDERED_AUTO_TEST (use_fwd_declared_trait_without_definition) {
+ BOOST_TEST(sizeof(is_unordered_set_impl((int_set*)0)) == sizeof(true_type));
+}
+
+#include <boost/unordered_set.hpp>
+
+UNORDERED_AUTO_TEST (use_fwd_declared_trait) {
+ boost::unordered_set<int> x;
+ BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
+
+ BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
+}
+
+UNORDERED_AUTO_TEST (use_set_fwd_declared_function) {
+ int_set x, y;
+ x.insert(1);
+ y.insert(2);
+ call_swap(x, y);
+
+ BOOST_TEST(y.find(1) != y.end());
+ BOOST_TEST(y.find(2) == y.end());
+
+ BOOST_TEST(x.find(1) == x.end());
+ BOOST_TEST(x.find(2) != x.end());
+
+ BOOST_TEST(!call_equals(x, y));
+ BOOST_TEST(call_not_equals(x, y));
+}
+
+UNORDERED_AUTO_TEST (use_multiset_fwd_declared_function) {
+ int_multiset x, y;
+ call_swap(x, y);
+ BOOST_TEST(call_equals(x, y));
+ BOOST_TEST(!call_not_equals(x, y));
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/incomplete_test.cpp b/src/boost/libs/unordered/test/unordered/incomplete_test.cpp
new file mode 100644
index 000000000..09afcba63
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/incomplete_test.cpp
@@ -0,0 +1,173 @@
+
+// Copyright 2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include <utility>
+
+namespace x {
+ struct D
+ {
+ boost::unordered_map<D, D> x;
+ };
+}
+
+namespace incomplete_test {
+ // Declare, but don't define some types.
+
+ struct value;
+ struct hash;
+ struct equals;
+ template <class T> struct allocator;
+
+ // Declare some instances
+
+ typedef boost::unordered_map<value, value, hash, equals,
+ allocator<std::pair<value const, value> > >
+ map;
+ typedef boost::unordered_multimap<value, value, hash, equals,
+ allocator<std::pair<value const, value> > >
+ multimap;
+ typedef boost::unordered_set<value, hash, equals, allocator<value> > set;
+ typedef boost::unordered_multiset<value, hash, equals, allocator<value> >
+ multiset;
+
+ // 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;
+ }
+ };
+
+ // This is a dubious way to implement an allocator, but good enough
+ // for this test.
+ template <typename T> struct allocator : std::allocator<T>
+ {
+ allocator() {}
+
+ template <typename T2>
+ allocator(const allocator<T2>& other) : std::allocator<T>(other)
+ {
+ }
+
+ template <typename T2>
+ allocator(const std::allocator<T2>& other) : std::allocator<T>(other)
+ {
+ }
+ };
+
+ // 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,
+ allocator<std::pair<struct1 const, struct1> > >
+ x;
+ };
+ struct struct2
+ {
+ boost::unordered_multimap<struct2, struct2, hash, equals,
+ allocator<std::pair<struct2 const, struct2> > >
+ x;
+ };
+ struct struct3
+ {
+ boost::unordered_set<struct3, hash, equals, allocator<struct3> > x;
+ };
+ struct struct4
+ {
+ boost::unordered_multiset<struct4, hash, equals, allocator<struct4> > x;
+ };
+
+ // Now define the value type.
+
+ struct value
+ {
+ };
+
+ // Create some instances.
+
+ incomplete_test::map m1;
+ incomplete_test::multimap m2;
+ incomplete_test::set s1;
+ incomplete_test::multiset s2;
+
+ incomplete_test::struct1 c1;
+ incomplete_test::struct2 c2;
+ incomplete_test::struct3 c3;
+ incomplete_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&);
+
+ 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()
+ {
+ incomplete_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.
+
+ incomplete_test::use_types();
+}
diff --git a/src/boost/libs/unordered/test/unordered/insert_hint_tests.cpp b/src/boost/libs/unordered/test/unordered/insert_hint_tests.cpp
new file mode 100644
index 000000000..c77fc2dc8
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/insert_hint_tests.cpp
@@ -0,0 +1,121 @@
+
+// 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../helpers/invariants.hpp"
+
+#include <map>
+#include <set>
+
+namespace insert_hint {
+ UNORDERED_AUTO_TEST (insert_hint_empty) {
+ typedef boost::unordered_multiset<int> container;
+ container x;
+ x.insert(x.cbegin(), 10);
+ BOOST_TEST_EQ(x.size(), 1u);
+ BOOST_TEST_EQ(x.count(10), 1u);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_AUTO_TEST (insert_hint_empty2) {
+ typedef boost::unordered_multimap<std::string, int> container;
+ container x;
+ x.emplace_hint(x.cbegin(), "hello", 50);
+ BOOST_TEST_EQ(x.size(), 1u);
+ BOOST_TEST_EQ(x.count("hello"), 1u);
+ BOOST_TEST_EQ(x.find("hello")->second, 50);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_AUTO_TEST (insert_hint_single) {
+ typedef boost::unordered_multiset<std::string> container;
+ container x;
+ x.insert("equal");
+ x.insert(x.cbegin(), "equal");
+ BOOST_TEST_EQ(x.size(), 2u);
+ BOOST_TEST_EQ(x.count("equal"), 2u);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_AUTO_TEST (insert_hint_single2) {
+ typedef boost::unordered_multimap<int, std::string> container;
+ container x;
+ x.emplace(10, "one");
+ x.emplace_hint(x.cbegin(), 10, "two");
+ BOOST_TEST_EQ(x.size(), 2u);
+ BOOST_TEST_EQ(x.count(10), 2u);
+
+ container::iterator it = x.find(10);
+ std::string v0 = (it++)->second;
+ std::string v1 = (it++)->second;
+
+ BOOST_TEST(v0 == "one" || v0 == "two");
+ BOOST_TEST(v1 == "one" || v1 == "two");
+ BOOST_TEST(v0 != v1);
+
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_AUTO_TEST (insert_hint_multiple) {
+ for (unsigned int size = 0; size < 10; ++size) {
+ for (unsigned int offset = 0; offset <= size; ++offset) {
+ typedef boost::unordered_multiset<std::string> container;
+ container x;
+
+ for (unsigned int i = 0; i < size; ++i) {
+ x.insert("multiple");
+ }
+
+ BOOST_TEST_EQ(x.size(), size);
+
+ container::const_iterator position = x.cbegin();
+ for (unsigned int i = 0; i < offset; ++i) {
+ ++position;
+ }
+
+ x.insert(position, "multiple");
+
+ BOOST_TEST_EQ(x.size(), size + 1u);
+ BOOST_TEST_EQ(x.count("multiple"), size + 1u);
+ test::check_equivalent_keys(x);
+ }
+ }
+ }
+
+ UNORDERED_AUTO_TEST (insert_hint_unique) {
+ typedef boost::unordered_set<int> container;
+ container x;
+ x.insert(x.cbegin(), 10);
+ BOOST_TEST_EQ(x.size(), 1u);
+ BOOST_TEST_EQ(x.count(10), 1u);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_AUTO_TEST (insert_hint_unique_single) {
+ typedef boost::unordered_set<int> container;
+ container x;
+ x.insert(10);
+
+ x.insert(x.cbegin(), 10);
+ BOOST_TEST_EQ(x.size(), 1u);
+ BOOST_TEST_EQ(x.count(10), 1u);
+ test::check_equivalent_keys(x);
+
+ x.insert(x.cbegin(), 20);
+ BOOST_TEST_EQ(x.size(), 2u);
+ BOOST_TEST_EQ(x.count(10), 1u);
+ BOOST_TEST_EQ(x.count(20), 1u);
+ test::check_equivalent_keys(x);
+ }
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/insert_node_type_fail.cpp b/src/boost/libs/unordered/test/unordered/insert_node_type_fail.cpp
new file mode 100644
index 000000000..eb34930fb
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/insert_node_type_fail.cpp
@@ -0,0 +1,34 @@
+
+// Copyright 2017 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 <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+
+int main()
+{
+#if defined(UNORDERED_TEST_MAP)
+ typedef boost::unordered_map<int, int> container;
+ container x;
+ x.emplace(1, 1);
+#elif defined(UNORDERED_TEST_MULTIMAP)
+ typedef boost::unordered_multimap<int, int> container;
+ container x;
+#elif defined(UNORDERED_TEST_SET)
+ typedef boost::unordered_set<int> container;
+ container x;
+ x.emplace(1);
+#elif defined(UNORDERED_TEST_MULTISET)
+ typedef boost::unordered_multiset<int> container;
+ container x;
+ x.emplace(1);
+#else
+#define UNORDERED_ERROR
+#endif
+
+#if !defined(UNORDERED_ERROR)
+ container::node_type n = x.extract(x.begin());
+ x.insert(n);
+#endif
+}
diff --git a/src/boost/libs/unordered/test/unordered/insert_stable_tests.cpp b/src/boost/libs/unordered/test/unordered/insert_stable_tests.cpp
new file mode 100644
index 000000000..4ea6a84bd
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/insert_stable_tests.cpp
@@ -0,0 +1,117 @@
+
+// Copyright 2007-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+
+namespace insert_stable {
+ struct member
+ {
+ int tag1_;
+ int tag2_;
+
+ member() : tag1_(0), tag2_(0) {}
+ member(int t1, int t2) : tag1_(t1), tag2_(t2) {}
+
+ friend bool operator==(member const& x, member const& y)
+ {
+ return x.tag1_ == y.tag1_;
+ }
+
+ friend bool operator!=(member const& x, member const& y)
+ {
+ return x.tag1_ != y.tag1_;
+ }
+ };
+}
+
+#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
+namespace boost
+#else
+namespace insert_stable
+#endif
+{
+ std::size_t hash_value(insert_stable::member const& x)
+ {
+ return static_cast<std::size_t>(x.tag1_);
+ }
+}
+
+// This is no longer supported, as there's no longer an efficient way to get to
+// the end of a group of equivalent nodes.
+#if 0
+
+UNORDERED_AUTO_TEST(stable_insert_test1)
+{
+ boost::unordered_multiset<insert_stable::member> x;
+
+ x.insert(insert_stable::member(1, 1));
+ x.insert(insert_stable::member(1, 2));
+ x.insert(insert_stable::member(1, 3));
+
+ BOOST_TEST(x.count(insert_stable::member(1, 4)) == 3);
+
+ boost::unordered_multiset<insert_stable::member>::const_iterator
+ it = x.begin(),
+ end = x.end();
+ BOOST_TEST(it != end);
+ if (it != end) {
+ BOOST_TEST(it->tag2_ == 1);
+ ++it;
+ }
+ BOOST_TEST(it != end);
+ if (it != end) {
+ BOOST_TEST(it->tag2_ == 2);
+ ++it;
+ }
+ BOOST_TEST(it != end);
+ if (it != end) {
+ BOOST_TEST(it->tag2_ == 3);
+ ++it;
+ }
+ BOOST_TEST(it == end);
+}
+
+UNORDERED_AUTO_TEST(stable_insert_test2)
+{
+ boost::unordered_multimap<insert_stable::member, int> x;
+ typedef boost::unordered_multimap<insert_stable::member,
+ int>::const_iterator iterator;
+
+ iterator it = x.emplace(insert_stable::member(1, 1), 1);
+ it = x.emplace(insert_stable::member(1, 2), 2);
+ it = x.emplace(insert_stable::member(1, 3), 3);
+
+ BOOST_TEST(x.count(insert_stable::member(1, 4)) == 3);
+
+ it = x.begin();
+ iterator end = x.end();
+ BOOST_TEST(it != end);
+ if (it != end) {
+ BOOST_TEST(it->first.tag2_ == 1 && it->second == 1);
+ ++it;
+ }
+ BOOST_TEST(it != end);
+ if (it != end) {
+ BOOST_TEST(it->first.tag2_ == 2 && it->second == 2);
+ ++it;
+ }
+ BOOST_TEST(it != end);
+ if (it != end) {
+ BOOST_TEST(it->first.tag2_ == 3 && it->second == 3);
+ ++it;
+ }
+ BOOST_TEST(it == end);
+}
+
+#endif
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/insert_tests.cpp b/src/boost/libs/unordered/test/unordered/insert_tests.cpp
new file mode 100644
index 000000000..7ddb41fd9
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/insert_tests.cpp
@@ -0,0 +1,1425 @@
+
+// Copyright 2006-2010 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)
+
+#if !defined(PIECEWISE_TEST_NAME)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/test.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/equivalent.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/input_iterator.hpp"
+#include "../helpers/helpers.hpp"
+
+namespace insert_tests {
+
+ test::seed_t initialize_seed(243432);
+
+ template <class X>
+ void unique_insert_tests1(X*, test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ typedef typename X::iterator iterator;
+ typedef test::ordered<X> ordered;
+
+ UNORDERED_SUB_TEST("insert(value) tests for containers with unique keys")
+ {
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ std::pair<iterator, bool> r1 = x.insert(*it);
+ std::pair<typename ordered::iterator, bool> r2 = tracker.insert(*it);
+
+ BOOST_TEST(r1.second == r2.second);
+ BOOST_TEST(*r1.first == *r2.first);
+
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert(rvalue) tests for containers with unique keys")
+ {
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ typename X::value_type value = *it;
+ std::pair<iterator, bool> r1 = x.insert(boost::move(value));
+ std::pair<typename ordered::iterator, bool> r2 = tracker.insert(*it);
+
+ BOOST_TEST(r1.second == r2.second);
+ BOOST_TEST(*r1.first == *r2.first);
+
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+ }
+
+ template <class X>
+ void equivalent_insert_tests1(X*, test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ UNORDERED_SUB_TEST(
+ "insert(value) tests for containers with equivalent keys")
+ {
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ typename X::iterator r1 = x.insert(*it);
+ typename test::ordered<X>::iterator r2 = tracker.insert(*it);
+
+ BOOST_TEST(*r1 == *r2);
+
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST(
+ "insert(rvalue) tests for containers with equivalent keys")
+ {
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ typename X::value_type value = *it;
+ typename X::iterator r1 = x.insert(boost::move(value));
+ typename test::ordered<X>::iterator r2 = tracker.insert(*it);
+
+ BOOST_TEST(*r1 == *r2);
+
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+ }
+
+ template <class X> void insert_tests2(X*, test::random_generator generator)
+ {
+ typedef typename test::ordered<X> tracker_type;
+ typedef typename X::iterator iterator;
+ typedef typename X::const_iterator const_iterator;
+ typedef typename tracker_type::iterator tracker_iterator;
+
+ UNORDERED_SUB_TEST("insert(begin(), value) tests")
+ {
+ test::check_instances check_;
+
+ X x;
+ tracker_type tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ iterator r1 = x.insert(x.begin(), *it);
+ tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
+ BOOST_TEST(*r1 == *r2);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert(end(), value) tests")
+ {
+ test::check_instances check_;
+
+ X x;
+ X const& x_const = x;
+ tracker_type tracker = test::create_ordered(x);
+
+ test::random_values<X> v(100, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ const_iterator r1 = x.insert(x_const.end(), *it);
+ tracker_iterator r2 = tracker.insert(tracker.end(), *it);
+ BOOST_TEST(*r1 == *r2);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert(pos, value) tests")
+ {
+ test::check_instances check_;
+
+ X x;
+ const_iterator pos = x.begin();
+ tracker_type tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ pos = x.insert(pos, *it);
+ tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
+ BOOST_TEST(*pos == *r2);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert(pos, rvalue) tests")
+ {
+ test::check_instances check_;
+
+ X x;
+ const_iterator pos = x.begin();
+ tracker_type tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ typename X::value_type value = *it;
+ pos = x.insert(pos, boost::move(value));
+ tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
+ BOOST_TEST(*pos == *r2);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert single item range tests")
+ {
+ test::check_instances check_;
+
+ X x;
+ tracker_type tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ x.insert(it, test::next(it));
+ tracker.insert(*it);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert range tests")
+ {
+ test::check_instances check_;
+
+ X x;
+
+ test::random_values<X> v(1000, generator);
+ x.insert(v.begin(), v.end());
+
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert range with rehash tests")
+ {
+ test::check_instances check_;
+
+ X x;
+
+ test::random_values<X> v(1000, generator);
+
+ x.insert(*v.begin());
+ x.clear();
+
+ x.insert(v.begin(), v.end());
+
+ test::check_container(x, v);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert input iterator range tests")
+ {
+ test::check_instances check_;
+
+ X x;
+
+ test::random_values<X> v(1000, generator);
+ 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);
+ }
+
+ UNORDERED_SUB_TEST("insert copy iterator range tests")
+ {
+ test::check_instances check_;
+
+ X x;
+
+ test::random_values<X> v(1000, generator);
+ x.insert(test::copy_iterator(v.begin()), test::copy_iterator(v.end()));
+ test::check_container(x, v);
+
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert copy iterator range test 2")
+ {
+ test::check_instances check_;
+
+ X x;
+
+ test::random_values<X> v1(500, generator);
+ test::random_values<X> v2(500, generator);
+ x.insert(test::copy_iterator(v1.begin()), test::copy_iterator(v1.end()));
+ x.insert(test::copy_iterator(v2.begin()), test::copy_iterator(v2.end()));
+
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert various ranges")
+ {
+ for (int i = 0; i < 100; ++i) {
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end();) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ typename test::random_values<X>::iterator next = it;
+ for (std::size_t j = test::random_value(20); j > 0; ++j) {
+ ++next;
+ if (next == v.end()) {
+ break;
+ }
+ }
+
+ x.insert(it, next);
+ tracker.insert(it, next);
+ it = next;
+
+ tracker.compare(x); // Slow, but I can't see any other way.
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+ }
+ }
+
+ template <class X>
+ void unique_emplace_tests1(X*, test::random_generator generator)
+ {
+ typedef typename X::iterator iterator;
+ typedef test::ordered<X> ordered;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ std::pair<iterator, bool> r1 = x.emplace(*it);
+ std::pair<typename ordered::iterator, bool> r2 = tracker.insert(*it);
+
+ BOOST_TEST(r1.second == r2.second);
+ BOOST_TEST(*r1.first == *r2.first);
+
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ template <class X>
+ void equivalent_emplace_tests1(X*, test::random_generator generator)
+ {
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ typename X::iterator r1 = x.emplace(*it);
+ typename test::ordered<X>::iterator r2 = tracker.insert(*it);
+
+ BOOST_TEST(*r1 == *r2);
+
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ template <class X>
+ void move_emplace_tests(X*, test::random_generator generator)
+ {
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ typename X::value_type value = *it;
+ x.emplace(boost::move(value));
+ tracker.insert(*it);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ template <class X> void default_emplace_tests(X*, test::random_generator)
+ {
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+ bool is_unique = test::has_unique_keys<X>::value;
+
+ X x;
+
+ x.emplace();
+ BOOST_TEST(x.size() == 1);
+ x.emplace();
+ BOOST_TEST(x.size() == (is_unique ? 1u : 2u));
+ x.emplace();
+ BOOST_TEST(x.size() == (is_unique ? 1u : 3u));
+
+ typename X::value_type y;
+ BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 3u));
+ BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
+
+ x.emplace(y);
+ BOOST_TEST(x.size() == (is_unique ? 1u : 4u));
+ BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 4u));
+ BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
+
+ x.clear();
+ BOOST_TEST(x.empty());
+ x.emplace(y);
+ BOOST_TEST(x.size() == 1);
+ x.emplace(y);
+ BOOST_TEST(x.size() == (is_unique ? 1u : 2u));
+
+ BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 2u));
+ BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
+#endif
+ }
+
+ template <class X> void map_tests(X*, test::random_generator generator)
+ {
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ x[it->first] = it->second;
+ tracker[it->first] = it->second;
+
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ template <class X> void map_tests2(X*, test::random_generator generator)
+ {
+ typedef typename X::iterator iterator;
+
+ UNORDERED_SUB_TEST("insert_or_assign")
+ {
+ test::check_instances check_;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ std::pair<iterator, bool> r = x.insert_or_assign(it->first, it->second);
+ BOOST_TEST(*r.first == *it);
+
+ tracker[it->first] = it->second;
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert_or_assign(begin)")
+ {
+ test::check_instances check_;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ iterator r = x.insert_or_assign(x.begin(), it->first, it->second);
+ BOOST_TEST(*r == *it);
+
+ tracker[it->first] = it->second;
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert_or_assign(end)")
+ {
+ test::check_instances check_;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ iterator r = x.insert_or_assign(x.end(), it->first, it->second);
+ BOOST_TEST(*r == *it);
+
+ tracker[it->first] = it->second;
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+
+ UNORDERED_SUB_TEST("insert_or_assign(last)")
+ {
+ test::check_instances check_;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+ iterator last = x.begin();
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ iterator r = x.insert_or_assign(last, it->first, it->second);
+ BOOST_TEST(*r == *it);
+
+ tracker[it->first] = it->second;
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+
+ last = r;
+ }
+
+ tracker.compare(x);
+ test::check_equivalent_keys(x);
+ }
+ }
+
+ template <class X>
+ void try_emplace_tests(X*, test::random_generator generator)
+ {
+ typedef typename X::iterator iterator;
+
+ UNORDERED_SUB_TEST("try_emplace(key, value)")
+ {
+ test::check_instances check_;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ iterator pos = x.find(it->first);
+ bool found = pos != x.end();
+
+ std::pair<typename X::iterator, bool> r =
+ x.try_emplace(it->first, it->second);
+ if (found) {
+ BOOST_TEST(pos == r.first);
+ BOOST_TEST(!r.second);
+ } else {
+ BOOST_TEST(r.second);
+ }
+ BOOST_TEST_EQ(r.first->first, it->first);
+ BOOST_TEST_EQ(r.first->second, it->second);
+
+ tracker.insert(*it);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+
+ typedef typename X::iterator iterator;
+
+ UNORDERED_SUB_TEST("try_emplace(begin(), key, value)")
+ {
+ test::check_instances check_;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ iterator pos = x.find(it->first);
+ bool found = pos != x.end();
+
+ typename X::iterator r =
+ x.try_emplace(r.begin(), it->first, it->second);
+ if (found) {
+ BOOST_TEST(pos == r);
+ }
+ BOOST_TEST_EQ(r->first, it->first);
+ BOOST_TEST_EQ(r->second, it->second);
+
+ tracker.insert(*it);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+
+ typedef typename X::iterator iterator;
+
+ UNORDERED_SUB_TEST("try_emplace(end(), key, value)")
+ {
+ test::check_instances check_;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ iterator pos = x.find(it->first);
+ bool found = pos != x.end();
+
+ typename X::iterator r = x.try_emplace(r.end(), it->first, it->second);
+ if (found) {
+ BOOST_TEST(pos == r);
+ }
+ BOOST_TEST_EQ(r->first, it->first);
+ BOOST_TEST_EQ(r->second, it->second);
+
+ tracker.insert(*it);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+
+ typedef typename X::iterator iterator;
+
+ UNORDERED_SUB_TEST("try_emplace(pos, key, value)")
+ {
+ test::check_instances check_;
+
+ X x;
+ test::ordered<X> tracker = test::create_ordered(x);
+
+ test::random_values<X> v(1000, generator);
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ typename X::size_type old_bucket_count = x.bucket_count();
+ float b = x.max_load_factor();
+
+ iterator pos = x.find(it->first);
+ bool found = pos != x.end();
+
+ typename X::iterator r = x.try_emplace(pos, it->first, it->second);
+ if (found) {
+ BOOST_TEST(pos == r);
+ }
+ BOOST_TEST_EQ(r->first, it->first);
+ BOOST_TEST_EQ(r->second, it->second);
+
+ tracker.insert(*it);
+ tracker.compare_key(x, *it);
+
+ if (static_cast<double>(x.size()) <
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+
+ test::check_equivalent_keys(x);
+ }
+ }
+
+ // Some tests for when the range's value type doesn't match the container's
+ // value type.
+
+ template <class X>
+ void map_insert_range_test1(X*, test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ typedef test::list<
+ std::pair<typename X::key_type, typename X::mapped_type> >
+ list;
+ test::random_values<X> v(1000, generator);
+ list l(v.begin(), v.end());
+
+ X x;
+ x.insert(l.begin(), l.end());
+
+ test::check_equivalent_keys(x);
+ }
+
+ template <class X>
+ void map_insert_range_test2(X*, test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ typedef test::list<
+ std::pair<typename X::key_type const, test::implicitly_convertible> >
+ list;
+ test::random_values<
+ boost::unordered_map<typename X::key_type, test::implicitly_convertible> >
+ v(1000, generator);
+ list l(v.begin(), v.end());
+
+ X x;
+ x.insert(l.begin(), l.end());
+
+ test::check_equivalent_keys(x);
+ }
+
+ boost::unordered_set<test::movable, test::hash, test::equal_to,
+ std::allocator<test::movable> >* test_set_std_alloc;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_set;
+ boost::unordered_multiset<test::movable, test::hash, test::equal_to,
+ test::allocator2<test::movable> >* test_multiset;
+ boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
+ test::allocator2<test::movable> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator1<test::object> >* test_multimap;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(unique_insert_tests1,
+ ((test_set_std_alloc)(test_set)(test_map))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(equivalent_insert_tests1,
+ ((test_multimap_std_alloc)(test_multiset)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(insert_tests2,
+ ((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(
+ test_multimap))((default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(unique_emplace_tests1,
+ ((test_set_std_alloc)(test_set)(test_map))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(equivalent_emplace_tests1,
+ ((test_multimap_std_alloc)(test_multiset)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(move_emplace_tests,
+ ((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)(
+ test_multiset)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(default_emplace_tests,
+ ((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)(
+ test_multiset)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(map_tests,
+ ((test_map))((default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(
+ map_tests2, ((test_map))((default_generator)(generate_collisions)))
+
+ UNORDERED_TEST(map_insert_range_test1,
+ ((test_multimap_std_alloc)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(map_insert_range_test2,
+ ((test_multimap_std_alloc)(test_map)(test_multimap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+
+ struct initialize_from_two_ints
+ {
+ int a, b;
+
+ friend std::size_t hash_value(initialize_from_two_ints const& x)
+ {
+ return static_cast<std::size_t>(x.a + x.b);
+ }
+
+ bool operator==(initialize_from_two_ints const& x) const
+ {
+ return a == x.a && b == x.b;
+ }
+ };
+
+ UNORDERED_AUTO_TEST (insert_initializer_list_set) {
+ boost::unordered_set<int> set;
+ set.insert({1, 2, 3, 1});
+ BOOST_TEST_EQ(set.size(), 3u);
+ BOOST_TEST(set.find(1) != set.end());
+ BOOST_TEST(set.find(4) == set.end());
+
+ boost::unordered_set<initialize_from_two_ints> set2;
+
+#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))
+ set2.insert({{1, 2}});
+#else
+ set2.insert({1, 2});
+#endif
+ BOOST_TEST(set2.size() == 1);
+ BOOST_TEST(set2.find({1, 2}) != set2.end());
+ BOOST_TEST(set2.find({2, 1}) == set2.end());
+
+ set2.insert({{3, 4}, {5, 6}, {7, 8}});
+ BOOST_TEST(set2.size() == 4);
+ BOOST_TEST(set2.find({1, 2}) != set2.end());
+ BOOST_TEST(set2.find({3, 4}) != set2.end());
+ BOOST_TEST(set2.find({5, 6}) != set2.end());
+ BOOST_TEST(set2.find({7, 8}) != set2.end());
+ BOOST_TEST(set2.find({8, 7}) == set2.end());
+
+ set2.insert({{2, 1}, {3, 4}});
+ BOOST_TEST(set2.size() == 5);
+ BOOST_TEST(set2.find({1, 2}) != set2.end());
+ BOOST_TEST(set2.find({2, 1}) != set2.end());
+ BOOST_TEST(set2.find({3, 4}) != set2.end());
+ BOOST_TEST(set2.find({5, 6}) != set2.end());
+ BOOST_TEST(set2.find({7, 8}) != set2.end());
+ BOOST_TEST(set2.find({8, 7}) == set2.end());
+ }
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
+
+ UNORDERED_AUTO_TEST (insert_initializer_list_multiset) {
+ boost::unordered_multiset<std::string> multiset;
+ // multiset.insert({});
+ BOOST_TEST(multiset.empty());
+ multiset.insert({"a"});
+ BOOST_TEST_EQ(multiset.size(), 1u);
+ BOOST_TEST(multiset.find("a") != multiset.end());
+ BOOST_TEST(multiset.find("b") == multiset.end());
+ multiset.insert({"a", "b"});
+ BOOST_TEST(multiset.size() == 3);
+ BOOST_TEST_EQ(multiset.count("a"), 2u);
+ BOOST_TEST_EQ(multiset.count("b"), 1u);
+ BOOST_TEST_EQ(multiset.count("c"), 0u);
+ }
+
+#endif
+
+ UNORDERED_AUTO_TEST (insert_initializer_list_map) {
+ boost::unordered_map<std::string, std::string> map;
+ // map.insert({});
+ BOOST_TEST(map.empty());
+ map.insert({{"a", "b"}, {"a", "b"}, {"d", ""}});
+ BOOST_TEST_EQ(map.size(), 2u);
+ }
+
+ UNORDERED_AUTO_TEST (insert_initializer_list_multimap) {
+ boost::unordered_multimap<std::string, std::string> multimap;
+ // multimap.insert({});
+ BOOST_TEST(multimap.empty());
+ multimap.insert({{"a", "b"}, {"a", "b"}, {"d", ""}});
+ BOOST_TEST_EQ(multimap.size(), 3u);
+ BOOST_TEST_EQ(multimap.count("a"), 2u);
+ }
+
+#endif
+
+ struct overloaded_constructor
+ {
+ overloaded_constructor(int x1_ = 1, int x2_ = 2, int x3_ = 3, int x4_ = 4)
+ : x1(x1_), x2(x2_), x3(x3_), x4(x4_)
+ {
+ }
+
+ int x1, x2, x3, x4;
+
+ bool operator==(overloaded_constructor const& rhs) const
+ {
+ return x1 == rhs.x1 && x2 == rhs.x2 && x3 == rhs.x3 && x4 == rhs.x4;
+ }
+
+ friend std::size_t hash_value(overloaded_constructor const& x)
+ {
+ std::size_t hash = 0;
+ boost::hash_combine(hash, x.x1);
+ boost::hash_combine(hash, x.x2);
+ boost::hash_combine(hash, x.x3);
+ boost::hash_combine(hash, x.x4);
+ return hash;
+ }
+ };
+
+ UNORDERED_AUTO_TEST (map_emplace_test) {
+ {
+ boost::unordered_map<int, overloaded_constructor, test::hash,
+ test::equal_to,
+ test::allocator1<std::pair<int const, overloaded_constructor> > >
+ x;
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+ x.emplace();
+ BOOST_TEST(
+ x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
+#endif
+
+ x.emplace(2, 3);
+ BOOST_TEST(
+ x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
+
+ x.try_emplace(5);
+ BOOST_TEST(
+ x.find(5) != x.end() && x.find(5)->second == overloaded_constructor());
+ }
+
+ {
+ boost::unordered_multimap<int, overloaded_constructor, test::hash,
+ test::equal_to,
+ test::allocator1<std::pair<int const, overloaded_constructor> > >
+ x;
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+ x.emplace();
+ BOOST_TEST(
+ x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
+#endif
+
+ x.emplace(2, 3);
+ BOOST_TEST(
+ x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
+ }
+ }
+
+ UNORDERED_AUTO_TEST (set_emplace_test) {
+ boost::unordered_set<overloaded_constructor> x;
+ overloaded_constructor check;
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+ x.emplace();
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+#endif
+
+ x.clear();
+ x.emplace(1);
+ check = overloaded_constructor(1);
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+
+ x.clear();
+ x.emplace(2, 3);
+ check = overloaded_constructor(2, 3);
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+
+ x.clear();
+ x.emplace(4, 5, 6);
+ check = overloaded_constructor(4, 5, 6);
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+
+ x.clear();
+ x.emplace(7, 8, 9, 10);
+ check = overloaded_constructor(7, 8, 9, 10);
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+ }
+
+ struct derived_from_piecewise_construct_t
+ : boost::unordered::piecewise_construct_t
+ {
+ };
+
+ derived_from_piecewise_construct_t piecewise_rvalue()
+ {
+ return derived_from_piecewise_construct_t();
+ }
+
+ struct convertible_to_piecewise
+ {
+ operator boost::unordered::piecewise_construct_t() const
+ {
+ return boost::unordered::piecewise_construct;
+ }
+ };
+
+ UNORDERED_AUTO_TEST (map_emplace_test2) {
+ // Emulating piecewise construction with boost::tuple bypasses the
+ // allocator's construct method, but still uses test destroy method.
+ test::detail::disable_construction_tracking _scoped;
+
+ {
+ boost::unordered_map<overloaded_constructor, overloaded_constructor,
+ boost::hash<overloaded_constructor>,
+ std::equal_to<overloaded_constructor>,
+ test::allocator1<
+ std::pair<overloaded_constructor const, overloaded_constructor> > >
+ x;
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
+ boost::make_tuple());
+ BOOST_TEST(
+ x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.emplace(
+ convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
+ BOOST_TEST(
+ x.find(overloaded_constructor(1)) != x.end() &&
+ x.find(overloaded_constructor(1))->second == overloaded_constructor());
+
+ x.emplace(piecewise_rvalue(), boost::make_tuple(2, 3),
+ boost::make_tuple(4, 5, 6));
+ BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
+ x.find(overloaded_constructor(2, 3))->second ==
+ overloaded_constructor(4, 5, 6));
+
+ derived_from_piecewise_construct_t d;
+ x.emplace(d, boost::make_tuple(9, 3, 1), boost::make_tuple(10));
+ BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
+ x.find(overloaded_constructor(9, 3, 1))->second ==
+ overloaded_constructor(10));
+
+ x.clear();
+
+ x.try_emplace(overloaded_constructor());
+ BOOST_TEST(
+ x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.try_emplace(1);
+ BOOST_TEST(
+ x.find(overloaded_constructor(1)) != x.end() &&
+ x.find(overloaded_constructor(1))->second == overloaded_constructor());
+
+ x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
+ BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
+ x.find(overloaded_constructor(2, 3))->second ==
+ overloaded_constructor(4, 5, 6));
+
+ x.clear();
+
+ x.try_emplace(x.begin(), overloaded_constructor());
+ BOOST_TEST(
+ x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.try_emplace(x.end(), 1);
+ BOOST_TEST(
+ x.find(overloaded_constructor(1)) != x.end() &&
+ x.find(overloaded_constructor(1))->second == overloaded_constructor());
+
+ x.try_emplace(x.begin(), overloaded_constructor(2, 3), 4, 5, 6);
+ BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
+ x.find(overloaded_constructor(2, 3))->second ==
+ overloaded_constructor(4, 5, 6));
+ }
+
+ {
+ boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
+ boost::hash<overloaded_constructor>,
+ std::equal_to<overloaded_constructor>,
+ test::allocator1<
+ std::pair<overloaded_constructor const, overloaded_constructor> > >
+ x;
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
+ boost::make_tuple());
+ BOOST_TEST(
+ x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.emplace(
+ convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
+ BOOST_TEST(
+ x.find(overloaded_constructor(1)) != x.end() &&
+ x.find(overloaded_constructor(1))->second == overloaded_constructor());
+
+ x.emplace(piecewise_rvalue(), boost::make_tuple(2, 3),
+ boost::make_tuple(4, 5, 6));
+ BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
+ x.find(overloaded_constructor(2, 3))->second ==
+ overloaded_constructor(4, 5, 6));
+
+ derived_from_piecewise_construct_t d;
+ x.emplace(d, boost::make_tuple(9, 3, 1), boost::make_tuple(10));
+ BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
+ x.find(overloaded_constructor(9, 3, 1))->second ==
+ overloaded_constructor(10));
+ }
+ }
+
+ UNORDERED_AUTO_TEST (set_emplace_test2) {
+ boost::unordered_set<
+ std::pair<overloaded_constructor, overloaded_constructor> >
+ x;
+ std::pair<overloaded_constructor, overloaded_constructor> check;
+
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
+ boost::make_tuple());
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+
+ x.clear();
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1),
+ boost::make_tuple(2, 3));
+ check =
+ std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+ }
+
+// Use the preprocessor to generate tests using different combinations of
+// boost/std piecewise_construct_t/tuple.
+
+#define PIECEWISE_TEST_NAME boost_tuple_piecewise_tests
+#define PIECEWISE_NAMESPACE boost::unordered
+#define TUPLE_NAMESPACE boost
+#define EMULATING_PIECEWISE_CONSTRUCTION 1
+#include "./insert_tests.cpp"
+
+#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
+
+#define PIECEWISE_TEST_NAME boost_tuple_std_piecewise_tests
+#define PIECEWISE_NAMESPACE std
+#define TUPLE_NAMESPACE boost
+#define EMULATING_PIECEWISE_CONSTRUCTION 1
+#include "./insert_tests.cpp"
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
+
+#define PIECEWISE_TEST_NAME std_tuple_boost_piecewise_tests
+#define PIECEWISE_NAMESPACE boost::unordered
+#define TUPLE_NAMESPACE std
+#define EMULATING_PIECEWISE_CONSTRUCTION 0
+#include "./insert_tests.cpp"
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
+ BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
+
+#define PIECEWISE_TEST_NAME std_piecewise_tests
+#define PIECEWISE_NAMESPACE std
+#define TUPLE_NAMESPACE std
+#define EMULATING_PIECEWISE_CONSTRUCTION 0
+#include "./insert_tests.cpp"
+
+#endif
+}
+
+RUN_TESTS_QUIET()
+
+#else // PIECEWISE_TEST_NAME
+
+UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
+#if EMULATING_PIECEWISE_CONSTRUCTION
+ test::detail::disable_construction_tracking _scoped;
+#endif
+
+ {
+ boost::unordered_map<overloaded_constructor, overloaded_constructor,
+ boost::hash<overloaded_constructor>,
+ std::equal_to<overloaded_constructor>,
+ test::allocator1<
+ std::pair<overloaded_constructor const, overloaded_constructor> > >
+ x;
+
+ x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
+ TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
+ BOOST_TEST(
+ x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
+ TUPLE_NAMESPACE::make_tuple());
+ BOOST_TEST(
+ x.find(overloaded_constructor(1)) != x.end() &&
+ x.find(overloaded_constructor(1))->second == overloaded_constructor());
+
+ x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
+ TUPLE_NAMESPACE::make_tuple(4, 5, 6));
+ BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
+ x.find(overloaded_constructor(2, 3))->second ==
+ overloaded_constructor(4, 5, 6));
+
+ derived_from_piecewise_construct_t d;
+ x.emplace(
+ d, TUPLE_NAMESPACE::make_tuple(9, 3, 1), TUPLE_NAMESPACE::make_tuple(10));
+ BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
+ x.find(overloaded_constructor(9, 3, 1))->second ==
+ overloaded_constructor(10));
+
+ x.clear();
+
+ x.try_emplace(overloaded_constructor());
+ BOOST_TEST(
+ x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.try_emplace(1);
+ BOOST_TEST(
+ x.find(overloaded_constructor(1)) != x.end() &&
+ x.find(overloaded_constructor(1))->second == overloaded_constructor());
+
+ x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
+ BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
+ x.find(overloaded_constructor(2, 3))->second ==
+ overloaded_constructor(4, 5, 6));
+ }
+ {
+ boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
+ boost::hash<overloaded_constructor>,
+ std::equal_to<overloaded_constructor>,
+ test::allocator1<
+ std::pair<overloaded_constructor const, overloaded_constructor> > >
+ x;
+
+ x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
+ TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
+ BOOST_TEST(
+ x.find(overloaded_constructor()) != x.end() &&
+ x.find(overloaded_constructor())->second == overloaded_constructor());
+
+ x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
+ TUPLE_NAMESPACE::make_tuple());
+ BOOST_TEST(
+ x.find(overloaded_constructor(1)) != x.end() &&
+ x.find(overloaded_constructor(1))->second == overloaded_constructor());
+
+ x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
+ TUPLE_NAMESPACE::make_tuple(4, 5, 6));
+ BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
+ x.find(overloaded_constructor(2, 3))->second ==
+ overloaded_constructor(4, 5, 6));
+
+ derived_from_piecewise_construct_t d;
+ x.emplace(
+ d, TUPLE_NAMESPACE::make_tuple(9, 3, 1), TUPLE_NAMESPACE::make_tuple(10));
+ BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
+ x.find(overloaded_constructor(9, 3, 1))->second ==
+ overloaded_constructor(10));
+ }
+}
+
+UNORDERED_AUTO_TEST (BOOST_PP_CAT(PIECEWISE_TEST_NAME, 2)) {
+#if EMULATING_PIECEWISE_CONSTRUCTION
+ test::detail::disable_construction_tracking _scoped;
+#endif
+
+ boost::unordered_set<
+ std::pair<overloaded_constructor, overloaded_constructor> >
+ x;
+ std::pair<overloaded_constructor, overloaded_constructor> check;
+
+ x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
+ TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+
+ x.clear();
+ x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
+ TUPLE_NAMESPACE::make_tuple(1), TUPLE_NAMESPACE::make_tuple(2, 3));
+ check =
+ std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
+ BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
+}
+
+#undef PIECEWISE_TEST_NAME
+#undef PIECEWISE_NAMESPACE
+#undef TUPLE_NAMESPACE
+#undef EMULATING_PIECEWISE_CONSTRUCTION
+
+#endif
diff --git a/src/boost/libs/unordered/test/unordered/link_test_1.cpp b/src/boost/libs/unordered/test/unordered/link_test_1.cpp
new file mode 100644
index 000000000..c32c3ac91
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/link_test_1.cpp
@@ -0,0 +1,26 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+void foo(boost::unordered_set<int>&, boost::unordered_map<int, int>&,
+ boost::unordered_multiset<int>&, boost::unordered_multimap<int, int>&);
+
+int main()
+{
+ boost::unordered_set<int> x1;
+ boost::unordered_map<int, int> x2;
+ boost::unordered_multiset<int> x3;
+ boost::unordered_multimap<int, int> x4;
+
+ foo(x1, x2, x3, x4);
+
+ return 0;
+}
diff --git a/src/boost/libs/unordered/test/unordered/link_test_2.cpp b/src/boost/libs/unordered/test/unordered/link_test_2.cpp
new file mode 100644
index 000000000..5ccf60d54
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/link_test_2.cpp
@@ -0,0 +1,30 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2,
+ 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);
+ x4.insert(std::make_pair(4, 5));
+}
diff --git a/src/boost/libs/unordered/test/unordered/load_factor_tests.cpp b/src/boost/libs/unordered/test/unordered/load_factor_tests.cpp
new file mode 100644
index 000000000..9006c1bdf
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/load_factor_tests.cpp
@@ -0,0 +1,97 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include <boost/limits.hpp>
+#include "../helpers/random_values.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+namespace load_factor_tests {
+
+ test::seed_t initialize_seed(783656);
+
+ template <class X> void set_load_factor_tests(X*)
+ {
+ X x;
+
+ BOOST_TEST(x.max_load_factor() == 1.0);
+ BOOST_TEST(x.load_factor() == 0);
+
+ // A valid implementation could fail these tests, but I think they're
+ // reasonable.
+ x.max_load_factor(2.0);
+ BOOST_TEST(x.max_load_factor() == 2.0);
+ x.max_load_factor(0.5);
+ BOOST_TEST(x.max_load_factor() == 0.5);
+ }
+
+ template <class X>
+ void insert_test(X*, float mlf, test::random_generator generator)
+ {
+ X x;
+ x.max_load_factor(mlf);
+ float b = x.max_load_factor();
+
+ test::random_values<X> values(1000, generator);
+
+ for (typename test::random_values<X>::const_iterator it = values.begin(),
+ end = values.end();
+ it != end; ++it) {
+ typename X::size_type old_size = x.size(),
+ old_bucket_count = x.bucket_count();
+ x.insert(*it);
+ if (static_cast<double>(old_size + 1) <=
+ b * static_cast<double>(old_bucket_count))
+ BOOST_TEST(x.bucket_count() == old_bucket_count);
+ }
+ }
+
+ template <class X>
+ void load_factor_insert_tests(X* ptr, test::random_generator generator)
+ {
+ insert_test(ptr, 1.0f, generator);
+ insert_test(ptr, 0.1f, generator);
+ insert_test(ptr, 100.0f, generator);
+
+ insert_test(ptr, (std::numeric_limits<float>::min)(), generator);
+
+ if (std::numeric_limits<float>::has_infinity)
+ insert_test(ptr, std::numeric_limits<float>::infinity(), generator);
+ }
+
+ boost::unordered_set<int>* int_set_ptr;
+ boost::unordered_multiset<int>* int_multiset_ptr;
+ boost::unordered_map<int, int>* int_map_ptr;
+ boost::unordered_multimap<int, int>* int_multimap_ptr;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(set_load_factor_tests,
+ ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)))
+
+ UNORDERED_TEST(load_factor_insert_tests,
+ ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))(
+ (default_generator)(generate_collisions)(limited_range)))
+}
+
+RUN_TESTS()
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
diff --git a/src/boost/libs/unordered/test/unordered/merge_tests.cpp b/src/boost/libs/unordered/test/unordered/merge_tests.cpp
new file mode 100644
index 000000000..897abb34c
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/merge_tests.cpp
@@ -0,0 +1,337 @@
+
+// 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/postfix.hpp"
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+
+#include "../helpers/count.hpp"
+#include "../helpers/helpers.hpp"
+#include "../helpers/invariants.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/test.hpp"
+#include "../helpers/tracker.hpp"
+#include "../objects/test.hpp"
+
+namespace merge_tests {
+
+ UNORDERED_AUTO_TEST (merge_set) {
+ boost::unordered_set<int> x;
+ boost::unordered_set<int> y;
+
+ x.merge(y);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(y.empty());
+
+ x.insert(10);
+ x.merge(y);
+ BOOST_TEST(x.size() == 1);
+ BOOST_TEST(x.count(10) == 1);
+ BOOST_TEST(y.empty());
+
+ y.merge(x);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(y.size() == 1);
+ BOOST_TEST(y.count(10) == 1);
+
+ x.insert(10);
+ x.insert(50);
+ y.insert(70);
+ y.insert(80);
+ x.merge(y);
+ BOOST_TEST_EQ(x.size(), 4u);
+ BOOST_TEST_EQ(y.size(), 1u);
+ BOOST_TEST_EQ(x.count(10), 1u);
+ BOOST_TEST_EQ(x.count(50), 1u);
+ BOOST_TEST_EQ(x.count(70), 1u);
+ BOOST_TEST_EQ(x.count(80), 1u);
+ BOOST_TEST_EQ(y.count(10), 1u);
+ BOOST_TEST_EQ(y.count(50), 0u);
+ BOOST_TEST_EQ(y.count(70), 0u);
+ BOOST_TEST_EQ(y.count(80), 0u);
+
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ }
+
+ UNORDERED_AUTO_TEST (merge_multiset) {
+ boost::unordered_multiset<int> x;
+ boost::unordered_multiset<int> y;
+
+ x.merge(y);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(y.empty());
+
+ x.insert(10);
+ x.merge(y);
+ BOOST_TEST(x.size() == 1);
+ BOOST_TEST(x.count(10) == 1);
+ BOOST_TEST(y.empty());
+
+ y.merge(x);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(y.size() == 1);
+ BOOST_TEST(y.count(10) == 1);
+
+ x.insert(10);
+ x.insert(50);
+ y.insert(70);
+ y.insert(80);
+ x.merge(y);
+ BOOST_TEST_EQ(x.size(), 5u);
+ BOOST_TEST_EQ(y.size(), 0u);
+ BOOST_TEST_EQ(x.count(10), 2u);
+ BOOST_TEST_EQ(x.count(50), 1u);
+ BOOST_TEST_EQ(x.count(70), 1u);
+ BOOST_TEST_EQ(x.count(80), 1u);
+ BOOST_TEST_EQ(y.count(10), 0u);
+ BOOST_TEST_EQ(y.count(50), 0u);
+ BOOST_TEST_EQ(y.count(70), 0u);
+ BOOST_TEST_EQ(y.count(80), 0u);
+
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ }
+
+ UNORDERED_AUTO_TEST (merge_set_and_multiset) {
+ boost::unordered_set<int> x;
+ boost::unordered_multiset<int> y;
+
+ x.merge(y);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(y.empty());
+
+ x.insert(10);
+ x.merge(y);
+ BOOST_TEST(x.size() == 1);
+ BOOST_TEST(x.count(10) == 1);
+ BOOST_TEST(y.empty());
+
+ y.merge(x);
+ BOOST_TEST(x.empty());
+ BOOST_TEST(y.size() == 1);
+ BOOST_TEST(y.count(10) == 1);
+
+ x.insert(10);
+ x.insert(50);
+ y.insert(70);
+ y.insert(80);
+ x.merge(y);
+ BOOST_TEST_EQ(x.size(), 4u);
+ BOOST_TEST_EQ(y.size(), 1u);
+ BOOST_TEST_EQ(x.count(10), 1u);
+ BOOST_TEST_EQ(x.count(50), 1u);
+ BOOST_TEST_EQ(x.count(70), 1u);
+ BOOST_TEST_EQ(x.count(80), 1u);
+ BOOST_TEST_EQ(y.count(10), 1u);
+ BOOST_TEST_EQ(y.count(50), 0u);
+ BOOST_TEST_EQ(y.count(70), 0u);
+ BOOST_TEST_EQ(y.count(80), 0u);
+
+ test::check_equivalent_keys(x);
+ test::check_equivalent_keys(y);
+ }
+
+ template <class X1, class X2>
+ void merge_empty_test(X1*, X2*, test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ test::random_values<X1> v(1000, generator);
+ X1 x1(v.begin(), v.end());
+ X2 x2;
+ x1.merge(x2);
+ test::check_container(x1, v);
+ BOOST_TEST(x2.empty());
+ test::check_equivalent_keys(x1);
+ test::check_equivalent_keys(x2);
+ }
+
+ template <class X>
+ void merge_into_empty_test(X*, test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ test::random_values<X> v(1000, generator);
+ X x1;
+ X x2(v.begin(), v.end());
+ x1.merge(x2);
+ test::check_container(x1, v);
+ BOOST_TEST(x2.empty());
+ test::check_equivalent_keys(x1);
+ test::check_equivalent_keys(x2);
+ }
+
+ template <class X1, class X2>
+ void merge_into_unique_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
+ test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ test::random_values<X1> v1(1000, generator);
+ test::random_values<X2> v2(1000, generator);
+ v1.insert(v2.begin(), test::next(v2.begin(), 100));
+ v2.insert(v1.begin(), test::next(v1.begin(), 100));
+
+ X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1),
+ test::equal_to(hash_equal1));
+ X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2),
+ test::equal_to(hash_equal2));
+
+ test::ordered<X1> tracker1 = test::create_ordered(x1);
+ test::ordered<X2> tracker2 = test::create_ordered(x2);
+ tracker1.insert(v1.begin(), v1.end());
+ for (typename X2::iterator it = x2.begin(); it != x2.end(); ++it) {
+ if (!tracker1.insert(*it).second) {
+ tracker2.insert(*it);
+ }
+ }
+
+ x1.merge(x2);
+
+ tracker1.compare(x1);
+ tracker2.compare(x2);
+ test::check_equivalent_keys(x1);
+ test::check_equivalent_keys(x2);
+ }
+
+ template <class X1, class X2>
+ void merge_into_equiv_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
+ test::random_generator generator)
+ {
+ test::check_instances check_;
+
+ test::random_values<X1> v1(1000, generator);
+ test::random_values<X2> v2(1000, generator);
+ v1.insert(v2.begin(), test::next(v2.begin(), 100));
+ v2.insert(v1.begin(), test::next(v1.begin(), 100));
+
+ X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1),
+ test::equal_to(hash_equal1));
+ X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2),
+ test::equal_to(hash_equal2));
+ x1.merge(x2);
+
+ test::ordered<X1> tracker1 = test::create_ordered(x1);
+ test::ordered<X2> tracker2 = test::create_ordered(x2);
+ tracker1.insert(v1.begin(), v1.end());
+ tracker2.insert(v2.begin(), v2.end());
+ tracker1.insert(tracker2.begin(), tracker2.end());
+ tracker2.clear();
+
+ tracker1.compare(x1);
+ tracker2.compare(x2);
+ test::check_equivalent_keys(x1);
+ test::check_equivalent_keys(x2);
+ }
+
+ boost::unordered_set<test::movable, test::hash, test::equal_to,
+ std::allocator<test::movable> >* test_set_std_alloc;
+ boost::unordered_multiset<test::movable, test::hash, test::equal_to,
+ std::allocator<test::movable> >* test_multiset_std_alloc;
+
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ std::allocator<test::object> >* test_map_std_alloc;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_multiset;
+
+ boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
+ test::allocator2<test::movable> >* test_map;
+ boost::unordered_multimap<test::movable, test::movable, test::hash,
+ test::equal_to, test::allocator2<test::movable> >* test_multimap;
+
+ using test::default_generator;
+ using test::generate_collisions;
+
+ // clang-format off
+UNORDERED_TEST(merge_empty_test,
+ ((test_set_std_alloc)(test_multiset_std_alloc))
+ ((test_set_std_alloc)(test_multiset_std_alloc))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_empty_test,
+ ((test_map_std_alloc)(test_multimap_std_alloc))
+ ((test_map_std_alloc)(test_multimap_std_alloc))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_empty_test,
+ ((test_set)(test_multiset))
+ ((test_set)(test_multiset))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_empty_test,
+ ((test_map)(test_multimap))
+ ((test_map)(test_multimap))
+ ((default_generator)(generate_collisions)))
+
+UNORDERED_TEST(merge_into_empty_test,
+ ((test_set_std_alloc)(test_multiset_std_alloc))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_empty_test,
+ ((test_map_std_alloc)(test_multimap_std_alloc))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_empty_test,
+ ((test_set)(test_multiset))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_empty_test,
+ ((test_map)(test_multimap))
+ ((default_generator)(generate_collisions)))
+
+UNORDERED_TEST(merge_into_unique_keys_test,
+ ((test_set_std_alloc))
+ ((test_set_std_alloc)(test_multiset_std_alloc))
+ ((0)(1)(2))
+ ((0)(1)(2))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_unique_keys_test,
+ ((test_map_std_alloc))
+ ((test_map_std_alloc)(test_multimap_std_alloc))
+ ((0)(1)(2))
+ ((0)(1)(2))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_unique_keys_test,
+ ((test_set))
+ ((test_set)(test_multiset))
+ ((0)(1)(2))
+ ((0)(1)(2))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_unique_keys_test,
+ ((test_map))
+ ((test_map)(test_multimap))
+ ((0)(1)(2))
+ ((0)(1)(2))
+ ((default_generator)(generate_collisions)))
+
+UNORDERED_TEST(merge_into_equiv_keys_test,
+ ((test_multiset_std_alloc))
+ ((test_set_std_alloc)(test_multiset_std_alloc))
+ ((0)(1)(2))
+ ((0)(1)(2))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_equiv_keys_test,
+ ((test_multimap_std_alloc))
+ ((test_map_std_alloc)(test_multimap_std_alloc))
+ ((0)(1)(2))
+ ((0)(1)(2))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_equiv_keys_test,
+ ((test_multiset))
+ ((test_set)(test_multiset))
+ ((0)(1)(2))
+ ((0)(1)(2))
+ ((default_generator)(generate_collisions)))
+UNORDERED_TEST(merge_into_equiv_keys_test,
+ ((test_multimap))
+ ((test_map)(test_multimap))
+ ((0)(1)(2))
+ ((0)(1)(2))
+ ((default_generator)(generate_collisions)))
+ // clang-format on
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/minimal_allocator.cpp b/src/boost/libs/unordered/test/unordered/minimal_allocator.cpp
new file mode 100644
index 000000000..a692443ee
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/minimal_allocator.cpp
@@ -0,0 +1,92 @@
+
+// Copyright 2011 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 "../objects/test.hpp"
+#include <boost/core/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/unordered/detail/implementation.hpp>
+
+template <class Tp> struct SimpleAllocator
+{
+ typedef Tp value_type;
+
+ SimpleAllocator() {}
+
+ template <class T> SimpleAllocator(const SimpleAllocator<T>&) {}
+
+ Tp* allocate(std::size_t n)
+ {
+ return static_cast<Tp*>(::operator new(n * sizeof(Tp)));
+ }
+
+ void deallocate(Tp* p, std::size_t) { ::operator delete((void*)p); }
+};
+
+template <typename T> void test_simple_allocator()
+{
+ test::check_instances check_;
+
+ typedef boost::unordered::detail::allocator_traits<SimpleAllocator<T> >
+ traits;
+
+ BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type,
+ SimpleAllocator<T> >::value));
+
+ BOOST_STATIC_ASSERT((boost::is_same<typename traits::value_type, T>::value));
+
+ BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T*>::value));
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<typename traits::const_pointer, T const*>::value));
+ // BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void*
+ // >::value));
+ // BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer,
+ // void const*>::value));
+
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value));
+
+#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
+ BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type,
+ std::make_unsigned<std::ptrdiff_t>::type>::value));
+#else
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<typename traits::size_type, std::size_t>::value));
+#endif
+
+ BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
+ BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
+ BOOST_TEST(!traits::propagate_on_container_swap::value);
+
+ // rebind_alloc
+ // rebind_traits
+
+ SimpleAllocator<T> a;
+
+ T* ptr1 = traits::allocate(a, 1);
+ // T* ptr2 = traits::allocate(a, 1, static_cast<void const*>(ptr1));
+
+ traits::construct(a, ptr1, T(10));
+ // traits::construct(a, ptr2, T(30), ptr1);
+
+ BOOST_TEST(*ptr1 == T(10));
+ // BOOST_TEST(*ptr2 == T(30));
+
+ traits::destroy(a, ptr1);
+ // traits::destroy(a, ptr2);
+
+ // traits::deallocate(a, ptr2, 1);
+ traits::deallocate(a, ptr1, 1);
+
+ traits::max_size(a);
+}
+
+int main()
+{
+ test_simple_allocator<int>();
+ test_simple_allocator<test::object>();
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/unordered/test/unordered/move_tests.cpp b/src/boost/libs/unordered/test/unordered/move_tests.cpp
new file mode 100644
index 000000000..82ba60113
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/move_tests.cpp
@@ -0,0 +1,372 @@
+
+// Copyright 2008-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../objects/test.hpp"
+#include "../objects/cxx11_allocator.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/equivalent.hpp"
+#include "../helpers/invariants.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+namespace move_tests {
+ test::seed_t initialize_seed(98624);
+#if defined(BOOST_UNORDERED_USE_MOVE) || \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#define BOOST_UNORDERED_TEST_MOVING 1
+#else
+#define BOOST_UNORDERED_TEST_MOVING 0
+#endif
+
+ template <class T> T empty(T*) { return T(); }
+
+ template <class T>
+ T create(test::random_values<T> const& v, test::object_count& count)
+ {
+ T x(v.begin(), v.end());
+ count = test::global_object_count;
+ return x;
+ }
+
+ template <class T>
+ T create(test::random_values<T> const& v, test::object_count& count,
+ typename T::hasher hf, typename T::key_equal eq,
+ typename T::allocator_type al, float mlf)
+ {
+ T x(0, hf, eq, al);
+ x.max_load_factor(mlf);
+ x.insert(v.begin(), v.end());
+ count = test::global_object_count;
+ return x;
+ }
+
+ template <class T>
+ void move_construct_tests1(T* ptr, test::random_generator const& generator)
+ {
+ typename T::hasher hf;
+ typename T::key_equal eq;
+ typename T::allocator_type al;
+
+ {
+ test::check_instances check_;
+
+ T y(empty(ptr));
+ BOOST_TEST(y.empty());
+ BOOST_TEST(test::equivalent(y.hash_function(), hf));
+ BOOST_TEST(test::equivalent(y.key_eq(), eq));
+ BOOST_TEST(test::equivalent(y.get_allocator(), al));
+ BOOST_TEST(y.max_load_factor() == 1.0);
+ test::check_equivalent_keys(y);
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(1000, generator);
+ test::object_count count;
+ T y(create(v, count));
+#if defined(BOOST_HAS_NRVO)
+ BOOST_TEST(count == test::global_object_count);
+#endif
+ test::check_container(y, v);
+ test::check_equivalent_keys(y);
+ }
+ }
+
+ template <class T>
+ void move_assign_tests1(T*, test::random_generator const& generator)
+ {
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(500, generator);
+ test::object_count count;
+ T y;
+ y = create(v, count);
+#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
+ BOOST_TEST(count == test::global_object_count);
+#endif
+ test::check_container(y, v);
+ test::check_equivalent_keys(y);
+ }
+ }
+
+ template <class T>
+ void move_construct_tests2(T*, test::random_generator const& generator)
+ {
+ typename T::hasher hf(1);
+ typename T::key_equal eq(1);
+ typename T::allocator_type al(1);
+ typename T::allocator_type al2(2);
+
+ test::object_count count;
+
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(500, generator);
+ T y(create(v, count, hf, eq, al, 0.5));
+#if defined(BOOST_HAS_NRVO)
+ BOOST_TEST(count == test::global_object_count);
+#endif
+ test::check_container(y, v);
+ BOOST_TEST(test::equivalent(y.hash_function(), hf));
+ BOOST_TEST(test::equivalent(y.key_eq(), eq));
+ BOOST_TEST(test::equivalent(y.get_allocator(), al));
+ BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
+ test::check_equivalent_keys(y);
+ }
+
+ {
+ test::check_instances check_;
+
+ // TODO: To do this correctly requires the fancy new allocator
+ // stuff.
+ test::random_values<T> v(500, generator);
+ T y(create(v, count, hf, eq, al, 2.0), al2);
+ BOOST_TEST(count != test::global_object_count);
+ test::check_container(y, v);
+ BOOST_TEST(test::equivalent(y.hash_function(), hf));
+ BOOST_TEST(test::equivalent(y.key_eq(), eq));
+ BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+ BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
+ test::check_equivalent_keys(y);
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(25, generator);
+ T y(create(v, count, hf, eq, al, 1.0), al);
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_TEST(count == test::global_object_count);
+#elif defined(BOOST_HAS_NRVO)
+ BOOST_TEST(
+ static_cast<std::size_t>(
+ test::global_object_count.constructions - count.constructions) <=
+ (test::is_set<T>::value ? 1 : 2) *
+ (test::has_unique_keys<T>::value ? 25 : v.size()));
+ BOOST_TEST(count.instances == test::global_object_count.instances);
+#else
+ BOOST_TEST(
+ static_cast<std::size_t>(
+ test::global_object_count.constructions - count.constructions) <=
+ (test::is_set<T>::value ? 2 : 4) *
+ (test::has_unique_keys<T>::value ? 25 : v.size()));
+ BOOST_TEST(count.instances == test::global_object_count.instances);
+#endif
+ test::check_container(y, v);
+ BOOST_TEST(test::equivalent(y.hash_function(), hf));
+ BOOST_TEST(test::equivalent(y.key_eq(), eq));
+ BOOST_TEST(test::equivalent(y.get_allocator(), al));
+ BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
+ test::check_equivalent_keys(y);
+ }
+ }
+
+ template <class T>
+ void move_assign_tests2(T*, test::random_generator const& generator)
+ {
+ typename T::hasher hf(1);
+ typename T::key_equal eq(1);
+ typename T::allocator_type al1(1);
+ typename T::allocator_type al2(2);
+ typedef typename T::allocator_type allocator_type;
+
+ {
+ test::random_values<T> v(500, generator);
+ test::random_values<T> v2(0, generator);
+ T y(v.begin(), v.end(), 0, hf, eq, al1);
+ test::object_count count;
+ y = create(v2, count, hf, eq, al2, 2.0);
+ BOOST_TEST(y.empty());
+ test::check_container(y, v2);
+ test::check_equivalent_keys(y);
+ BOOST_TEST(y.max_load_factor() == 2.0);
+
+#if defined(BOOST_HAS_NRVO)
+ if (BOOST_UNORDERED_TEST_MOVING
+ ? (bool)allocator_type::is_propagate_on_move
+ : (bool)allocator_type::is_propagate_on_assign) {
+ BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+ } else {
+ BOOST_TEST(test::equivalent(y.get_allocator(), al1));
+ }
+#endif
+ }
+
+ {
+ test::random_values<T> v(500, generator);
+ test::object_count count;
+ T y(0, hf, eq, al1);
+ y = create(v, count, hf, eq, al2, 0.5);
+#if defined(BOOST_HAS_NRVO)
+ if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
+ BOOST_TEST(count == test::global_object_count);
+ }
+#endif
+ test::check_container(y, v);
+ test::check_equivalent_keys(y);
+ BOOST_TEST(y.max_load_factor() == 0.5);
+
+#if defined(BOOST_HAS_NRVO)
+ if (BOOST_UNORDERED_TEST_MOVING
+ ? (bool)allocator_type::is_propagate_on_move
+ : (bool)allocator_type::is_propagate_on_assign) {
+ BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+ } else {
+ BOOST_TEST(test::equivalent(y.get_allocator(), al1));
+ }
+#endif
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v(500, generator);
+ T y(0, hf, eq, al1);
+
+ T x(0, hf, eq, al2);
+ x.max_load_factor(0.25);
+ x.insert(v.begin(), v.end());
+
+ test::object_count count = test::global_object_count;
+ y = boost::move(x);
+ if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
+ BOOST_TEST(count == test::global_object_count);
+ }
+ test::check_container(y, v);
+ test::check_equivalent_keys(y);
+ BOOST_TEST(y.max_load_factor() == 0.25);
+
+ if (BOOST_UNORDERED_TEST_MOVING
+ ? (bool)allocator_type::is_propagate_on_move
+ : (bool)allocator_type::is_propagate_on_assign) {
+ BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+ } else {
+ BOOST_TEST(test::equivalent(y.get_allocator(), al1));
+ }
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<T> v1(1000, generator);
+ test::random_values<T> v2(200, generator);
+
+ T x(0, hf, eq, al2);
+ x.max_load_factor(0.5);
+ x.insert(v2.begin(), v2.end());
+
+ test::object_count count1 = test::global_object_count;
+
+ T y(v1.begin(), v1.end(), 0, hf, eq, al1);
+ y = boost::move(x);
+
+ test::object_count count2 = test::global_object_count;
+
+ if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
+ BOOST_TEST(count1.instances == test::global_object_count.instances);
+ BOOST_TEST(
+ count2.constructions == test::global_object_count.constructions);
+ }
+
+ test::check_container(y, v2);
+ test::check_equivalent_keys(y);
+ BOOST_TEST(y.max_load_factor() == 0.5);
+
+ if (BOOST_UNORDERED_TEST_MOVING
+ ? (bool)allocator_type::is_propagate_on_move
+ : (bool)allocator_type::is_propagate_on_assign) {
+ BOOST_TEST(test::equivalent(y.get_allocator(), al2));
+ } else {
+ BOOST_TEST(test::equivalent(y.get_allocator(), al1));
+ }
+ }
+ }
+
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ std::allocator<test::object> >* test_map_std_alloc;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator2<test::object> >* test_multimap;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_move> >*
+ test_set_prop_move;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_move> >*
+ test_multiset_prop_move;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_move> >*
+ test_map_prop_move;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::cxx11_allocator<test::object, test::propagate_move> >*
+ test_multimap_prop_move;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_move> >*
+ test_set_no_prop_move;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_move> >*
+ test_multiset_no_prop_move;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_move> >*
+ test_map_no_prop_move;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_move> >*
+ test_multimap_no_prop_move;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(move_construct_tests1,
+ ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
+ test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
+ test_multimap_prop_move)(test_set_no_prop_move)(
+ test_multiset_no_prop_move)(test_map_no_prop_move)(
+ test_multimap_no_prop_move))(
+ (default_generator)(generate_collisions)(limited_range)))
+ UNORDERED_TEST(move_assign_tests1,
+ ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
+ test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
+ test_multimap_prop_move)(test_set_no_prop_move)(
+ test_multiset_no_prop_move)(test_map_no_prop_move)(
+ test_multimap_no_prop_move))(
+ (default_generator)(generate_collisions)(limited_range)))
+ UNORDERED_TEST(move_construct_tests2,
+ ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)(
+ test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
+ test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
+ test_multimap_no_prop_move))(
+ (default_generator)(generate_collisions)(limited_range)))
+ UNORDERED_TEST(move_assign_tests2,
+ ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)(
+ test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
+ test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
+ test_multimap_no_prop_move))(
+ (default_generator)(generate_collisions)(limited_range)))
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/node_handle_tests.cpp b/src/boost/libs/unordered/test/unordered/node_handle_tests.cpp
new file mode 100644
index 000000000..2d5b1eab2
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/node_handle_tests.cpp
@@ -0,0 +1,424 @@
+
+// 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/postfix.hpp"
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+
+#include "../helpers/helpers.hpp"
+#include "../helpers/metafunctions.hpp"
+#include "../helpers/test.hpp"
+#include <boost/core/pointer_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <set>
+#include <string>
+
+UNORDERED_AUTO_TEST (example1) {
+ typedef boost::unordered_map<int, std::string>::insert_return_type
+ insert_return_type;
+
+ boost::unordered_map<int, std::string> src;
+ src.emplace(1, "one");
+ src.emplace(2, "two");
+ src.emplace(3, "buckle my shoe");
+ boost::unordered_map<int, std::string> dst;
+ dst.emplace(3, "three");
+
+ dst.insert(src.extract(src.find(1)));
+ dst.insert(src.extract(2));
+ insert_return_type r = dst.insert(src.extract(3));
+
+ BOOST_TEST(src.empty());
+ BOOST_TEST(dst.size() == 3);
+ BOOST_TEST(dst[1] == "one");
+ BOOST_TEST(dst[2] == "two");
+ BOOST_TEST(dst[3] == "three");
+ BOOST_TEST(!r.inserted);
+ BOOST_TEST(r.position == dst.find(3));
+ BOOST_TEST(r.node.mapped() == "buckle my shoe");
+}
+
+UNORDERED_AUTO_TEST (example2) {
+ boost::unordered_set<int> src;
+ src.insert(1);
+ src.insert(3);
+ src.insert(5);
+ boost::unordered_set<int> dst;
+ dst.insert(2);
+ dst.insert(4);
+ dst.insert(5);
+ // dst.merge(src);
+ // Merge src into dst.
+ // src == {5}
+ // dst == {1, 2, 3, 4, 5}
+}
+
+UNORDERED_AUTO_TEST (example3) {
+ typedef boost::unordered_set<int>::iterator iterator;
+
+ boost::unordered_set<int> src;
+ src.insert(1);
+ src.insert(3);
+ src.insert(5);
+ boost::unordered_set<int> dst;
+ dst.insert(2);
+ dst.insert(4);
+ dst.insert(5);
+ for (iterator i = src.begin(); i != src.end();) {
+ std::pair<iterator, iterator> p = dst.equal_range(*i);
+ if (p.first == p.second)
+ dst.insert(p.first, src.extract(i++));
+ else
+ ++i;
+ }
+ BOOST_TEST(src.size() == 1);
+ BOOST_TEST(*src.begin() == 5);
+
+ std::set<int> dst2(dst.begin(), dst.end());
+ std::set<int>::iterator it = dst2.begin();
+ BOOST_TEST(*it++ == 1);
+ BOOST_TEST(*it++ == 2);
+ BOOST_TEST(*it++ == 3);
+ BOOST_TEST(*it++ == 4);
+ BOOST_TEST(*it++ == 5);
+ BOOST_TEST(it == dst2.end());
+}
+
+UNORDERED_AUTO_TEST (failed_insertion_with_hint) {
+ {
+ boost::unordered_set<int> src;
+ boost::unordered_set<int> dst;
+ src.emplace(10);
+ src.emplace(20);
+ dst.emplace(10);
+ dst.emplace(20);
+
+ boost::unordered_set<int>::node_type nh = src.extract(10);
+
+ BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
+ BOOST_TEST(nh);
+ BOOST_TEST(!nh.empty());
+ BOOST_TEST(nh.value() == 10);
+
+ BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
+ BOOST_TEST(nh);
+ BOOST_TEST(!nh.empty());
+ BOOST_TEST(nh.value() == 10);
+
+ BOOST_TEST(src.count(10) == 0);
+ BOOST_TEST(src.count(20) == 1);
+ BOOST_TEST(dst.count(10) == 1);
+ BOOST_TEST(dst.count(20) == 1);
+ }
+
+ {
+ boost::unordered_map<int, int> src;
+ boost::unordered_map<int, int> dst;
+ src.emplace(10, 30);
+ src.emplace(20, 5);
+ dst.emplace(10, 20);
+ dst.emplace(20, 2);
+
+ boost::unordered_map<int, int>::node_type nh = src.extract(10);
+ BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
+ BOOST_TEST(nh);
+ BOOST_TEST(!nh.empty());
+ BOOST_TEST(nh.key() == 10);
+ BOOST_TEST(nh.mapped() == 30);
+ BOOST_TEST(dst[10] == 20);
+
+ BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
+ BOOST_TEST(nh);
+ BOOST_TEST(!nh.empty());
+ BOOST_TEST(nh.key() == 10);
+ BOOST_TEST(nh.mapped() == 30);
+ BOOST_TEST(dst[10] == 20);
+
+ BOOST_TEST(src.count(10) == 0);
+ BOOST_TEST(src.count(20) == 1);
+ BOOST_TEST(dst.count(10) == 1);
+ BOOST_TEST(dst.count(20) == 1);
+ }
+}
+
+template <typename NodeHandle>
+bool node_handle_compare(
+ NodeHandle const& nh, typename NodeHandle::value_type const& x)
+{
+ return x == nh.value();
+}
+
+template <typename NodeHandle>
+bool node_handle_compare(
+ NodeHandle const& nh, std::pair<typename NodeHandle::key_type const,
+ typename NodeHandle::mapped_type> const& x)
+{
+ return x.first == nh.key() && x.second == nh.mapped();
+}
+
+template <typename Container> void node_handle_tests_impl(Container& c)
+{
+ typedef typename Container::node_type node_type;
+
+ typename Container::value_type value = *c.begin();
+
+ node_type n1;
+ BOOST_TEST(!n1);
+ BOOST_TEST(n1.empty());
+
+ node_type n2 = c.extract(c.begin());
+ BOOST_TEST(n2);
+ BOOST_TEST(!n2.empty());
+ node_handle_compare(n2, value);
+
+ node_type n3 = boost::move(n2);
+ BOOST_TEST(n3);
+ BOOST_TEST(!n2);
+ node_handle_compare(n3, value);
+ // TODO: Check that n2 doesn't have an allocator?
+ // Maybe by swapping and observing that the allocator is
+ // swapped rather than moved?
+
+ n1 = boost::move(n3);
+ BOOST_TEST(n1);
+ BOOST_TEST(!n3);
+ node_handle_compare(n1, value);
+
+ // Self move-assignment empties the node_handle.
+ n1 = boost::move(n1);
+ BOOST_TEST(!n1);
+
+ n3 = boost::move(n3);
+ BOOST_TEST(!n3);
+
+ typename Container::value_type value1 = *c.begin();
+ n1 = c.extract(c.begin());
+ typename Container::value_type value2 = *c.begin();
+ n2 = c.extract(c.begin());
+ n3 = node_type();
+
+ node_handle_compare(n1, value1);
+ node_handle_compare(n2, value2);
+ n1.swap(n2);
+ BOOST_TEST(n1);
+ BOOST_TEST(n2);
+ node_handle_compare(n1, value2);
+ node_handle_compare(n2, value1);
+
+ BOOST_TEST(n1);
+ BOOST_TEST(!n3);
+ n1.swap(n3);
+ BOOST_TEST(!n1);
+ BOOST_TEST(n3);
+ node_handle_compare(n3, value2);
+
+ BOOST_TEST(!n1);
+ BOOST_TEST(n2);
+ n1.swap(n2);
+ BOOST_TEST(n1);
+ BOOST_TEST(!n2);
+ node_handle_compare(n1, value1);
+
+ node_type n4;
+ BOOST_TEST(!n2);
+ BOOST_TEST(!n4);
+ n2.swap(n4);
+ BOOST_TEST(!n2);
+ BOOST_TEST(!n4);
+}
+
+UNORDERED_AUTO_TEST (node_handle_tests) {
+ boost::unordered_set<int> x1;
+ x1.emplace(100);
+ x1.emplace(140);
+ x1.emplace(-55);
+ node_handle_tests_impl(x1);
+
+ boost::unordered_map<int, std::string> x2;
+ x2.emplace(10, "ten");
+ x2.emplace(-23, "twenty");
+ x2.emplace(-76, "thirty");
+ node_handle_tests_impl(x2);
+}
+
+template <typename Container1, typename Container2>
+void insert_node_handle_unique(Container1& c1, Container2& c2)
+{
+ typedef typename Container1::node_type node_type;
+ typedef typename Container1::value_type value_type;
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<node_type, typename Container2::node_type>::value));
+
+ typedef typename Container1::insert_return_type insert_return_type1;
+ typedef typename Container2::insert_return_type insert_return_type2;
+
+ insert_return_type1 r1 = c1.insert(node_type());
+ insert_return_type2 r2 = c2.insert(node_type());
+ BOOST_TEST(!r1.inserted);
+ BOOST_TEST(!r1.node);
+ BOOST_TEST(r1.position == c1.end());
+ BOOST_TEST(!r2.inserted);
+ BOOST_TEST(!r2.node);
+ BOOST_TEST(r2.position == c2.end());
+
+ while (!c1.empty()) {
+ value_type v = *c1.begin();
+ value_type const* v_ptr = boost::to_address(c1.begin());
+ std::size_t count = c2.count(test::get_key<Container1>(v));
+ insert_return_type2 r = c2.insert(c1.extract(c1.begin()));
+ if (!count) {
+ BOOST_TEST(r.inserted);
+ BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
+ BOOST_TEST(r.position != c2.end());
+ BOOST_TEST(boost::to_address(r.position) == v_ptr);
+ BOOST_TEST(!r.node);
+ } else {
+ BOOST_TEST(!r.inserted);
+ BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
+ BOOST_TEST(r.position != c2.end());
+ BOOST_TEST(
+ test::get_key<Container2>(*r.position) == test::get_key<Container2>(v));
+ BOOST_TEST(r.node);
+ node_handle_compare(r.node, v);
+ }
+ }
+}
+
+template <typename Container1, typename Container2>
+void insert_node_handle_unique2(Container1& c1, Container2& c2)
+{
+ typedef typename Container1::node_type node_type;
+ typedef typename Container1::value_type value_type;
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<node_type, typename Container2::node_type>::value));
+
+ // typedef typename Container1::insert_return_type
+ // insert_return_type1;
+ typedef typename Container2::insert_return_type insert_return_type2;
+
+ while (!c1.empty()) {
+ value_type v = *c1.begin();
+ value_type const* v_ptr = boost::to_address(c1.begin());
+ std::size_t count = c2.count(test::get_key<Container1>(v));
+ insert_return_type2 r = c2.insert(c1.extract(test::get_key<Container1>(v)));
+ if (r.inserted) {
+ BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
+ BOOST_TEST(r.position != c2.end());
+ BOOST_TEST(boost::to_address(r.position) == v_ptr);
+ BOOST_TEST(!r.node);
+ } else {
+ BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
+ BOOST_TEST(r.position != c2.end());
+ BOOST_TEST(
+ test::get_key<Container2>(*r.position) == test::get_key<Container2>(v));
+ BOOST_TEST(r.node);
+ node_handle_compare(r.node, v);
+ }
+ }
+}
+
+template <typename Container1, typename Container2>
+void insert_node_handle_equiv(Container1& c1, Container2& c2)
+{
+ typedef typename Container1::node_type node_type;
+ typedef typename Container1::value_type value_type;
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<node_type, typename Container2::node_type>::value));
+
+ typedef typename Container1::iterator iterator1;
+ typedef typename Container2::iterator iterator2;
+
+ iterator1 r1 = c1.insert(node_type());
+ iterator2 r2 = c2.insert(node_type());
+ BOOST_TEST(r1 == c1.end());
+ BOOST_TEST(r2 == c2.end());
+
+ while (!c1.empty()) {
+ value_type v = *c1.begin();
+ value_type const* v_ptr = boost::to_address(c1.begin());
+ std::size_t count = c2.count(test::get_key<Container1>(v));
+ iterator2 r = c2.insert(c1.extract(c1.begin()));
+ BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
+ BOOST_TEST(r != c2.end());
+ BOOST_TEST(boost::to_address(r) == v_ptr);
+ }
+}
+
+struct hash_thing
+{
+ std::size_t operator()(int x) const
+ {
+ return static_cast<std::size_t>(x * 13 + 5);
+ }
+};
+
+UNORDERED_AUTO_TEST (insert_node_handle_unique_tests) {
+ {
+ boost::unordered_set<int> x1;
+ boost::unordered_set<int> x2;
+ x1.emplace(100);
+ x1.emplace(140);
+ x1.emplace(-55);
+ x2.emplace(140);
+ insert_node_handle_unique(x1, x2);
+ BOOST_TEST(x2.size() == 3);
+ }
+
+ {
+ boost::unordered_map<int, int, hash_thing> x1;
+ boost::unordered_map<int, int> x2;
+ x1.emplace(67, 50);
+ x1.emplace(23, 45);
+ x1.emplace(18, 19);
+ x2.emplace(23, 50);
+ x2.emplace(12, 49);
+ insert_node_handle_unique(x1, x2);
+ BOOST_TEST(x2.size() == 4);
+ }
+}
+
+UNORDERED_AUTO_TEST (insert_node_handle_equiv_tests) {
+ {
+ boost::unordered_multimap<int, int, hash_thing> x1;
+ boost::unordered_multimap<int, int> x2;
+ x1.emplace(67, 50);
+ x1.emplace(67, 100);
+ x1.emplace(23, 45);
+ x1.emplace(18, 19);
+ x2.emplace(23, 50);
+ x2.emplace(12, 49);
+ insert_node_handle_equiv(x1, x2);
+ BOOST_TEST(x2.size() == 6);
+ }
+}
+
+UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) {
+ {
+ boost::unordered_set<int> x1;
+ boost::unordered_set<int> x2;
+ x1.emplace(100);
+ x1.emplace(140);
+ x1.emplace(-55);
+ x2.emplace(140);
+ insert_node_handle_unique2(x1, x2);
+ BOOST_TEST(x2.size() == 3);
+ }
+
+ {
+ boost::unordered_map<int, int, hash_thing> x1;
+ boost::unordered_map<int, int> x2;
+ x1.emplace(67, 50);
+ x1.emplace(23, 45);
+ x1.emplace(18, 19);
+ x2.emplace(23, 50);
+ x2.emplace(12, 49);
+ insert_node_handle_unique2(x1, x2);
+ BOOST_TEST(x2.size() == 4);
+ }
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/noexcept_tests.cpp b/src/boost/libs/unordered/test/unordered/noexcept_tests.cpp
new file mode 100644
index 000000000..454e7c23c
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/noexcept_tests.cpp
@@ -0,0 +1,320 @@
+
+// Copyright 2013 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+// conditional expression is constant
+#pragma warning(disable : 4127)
+#endif
+
+namespace noexcept_tests {
+ // Test the noexcept is set correctly for the move constructor.
+
+ struct hash_possible_exception : boost::hash<int>
+ {
+ hash_possible_exception(hash_possible_exception const&) {}
+ hash_possible_exception& operator=(hash_possible_exception const&)
+ {
+ return *this;
+ }
+ };
+
+ struct equal_to_possible_exception : std::equal_to<int>
+ {
+ equal_to_possible_exception(equal_to_possible_exception const&) {}
+ equal_to_possible_exception& operator=(equal_to_possible_exception const&)
+ {
+ return *this;
+ }
+ };
+
+ // Test that the move constructor does actually move without throwing
+ // an exception when it claims to.
+
+ struct test_exception
+ {
+ };
+
+ bool throwing_test_exception = false;
+ void test_throw(char const* name)
+ {
+ if (throwing_test_exception) {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Throw exception in: " << name
+ << std::endl;
+ throw test_exception();
+ }
+ }
+
+ template <bool nothrow_move_construct, bool nothrow_move_assign,
+ bool nothrow_swap>
+ class hash_nothrow : boost::hash<int>
+ {
+ BOOST_COPYABLE_AND_MOVABLE(hash_nothrow)
+
+ typedef boost::hash<int> base;
+
+ public:
+ hash_nothrow(BOOST_RV_REF(hash_nothrow))
+ BOOST_NOEXCEPT_IF(nothrow_move_construct)
+ {
+ if (!nothrow_move_construct) {
+ test_throw("Move Constructor");
+ }
+ }
+
+ hash_nothrow() { test_throw("Constructor"); }
+ hash_nothrow(hash_nothrow const&) { test_throw("Copy"); }
+ hash_nothrow& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow))
+ {
+ test_throw("Assign");
+ return *this;
+ }
+ hash_nothrow& operator=(BOOST_RV_REF(hash_nothrow))
+ BOOST_NOEXCEPT_IF(nothrow_move_assign)
+ {
+ if (!nothrow_move_assign) {
+ test_throw("Move Assign");
+ }
+ return *this;
+ }
+ std::size_t operator()(int x) const
+ {
+ test_throw("Operator");
+ return static_cast<base const&>(*this)(x);
+ }
+ friend void swap(hash_nothrow&, hash_nothrow&)
+ BOOST_NOEXCEPT_IF(nothrow_swap)
+ {
+ if (!nothrow_swap) {
+ test_throw("Swap");
+ }
+ }
+ };
+
+ typedef hash_nothrow<true, false, false> hash_nothrow_move_construct;
+ typedef hash_nothrow<false, true, false> hash_nothrow_move_assign;
+ typedef hash_nothrow<false, false, true> hash_nothrow_swap;
+
+ template <bool nothrow_move_construct, bool nothrow_move_assign,
+ bool nothrow_swap>
+ class equal_to_nothrow
+ {
+ BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow)
+
+ typedef boost::hash<int> base;
+
+ public:
+ equal_to_nothrow(BOOST_RV_REF(equal_to_nothrow))
+ BOOST_NOEXCEPT_IF(nothrow_move_construct)
+ {
+ if (!nothrow_move_construct) {
+ test_throw("Move Constructor");
+ }
+ }
+
+ equal_to_nothrow() { test_throw("Constructor"); }
+ equal_to_nothrow(equal_to_nothrow const&) { test_throw("Copy"); }
+ equal_to_nothrow& operator=(BOOST_COPY_ASSIGN_REF(equal_to_nothrow))
+ {
+ test_throw("Assign");
+ return *this;
+ }
+ equal_to_nothrow& operator=(BOOST_RV_REF(equal_to_nothrow))
+ BOOST_NOEXCEPT_IF(nothrow_move_assign)
+ {
+ if (!nothrow_move_assign) {
+ test_throw("Move Assign");
+ }
+ return *this;
+ }
+ std::size_t operator()(int x, int y) const
+ {
+ test_throw("Operator");
+ return x == y;
+ }
+ friend void swap(equal_to_nothrow&, equal_to_nothrow&)
+ BOOST_NOEXCEPT_IF(nothrow_swap)
+ {
+ if (!nothrow_swap) {
+ test_throw("Swap");
+ }
+ }
+ };
+
+ typedef equal_to_nothrow<true, false, false> equal_to_nothrow_move_construct;
+ typedef equal_to_nothrow<false, true, false> equal_to_nothrow_move_assign;
+ typedef equal_to_nothrow<false, false, true> equal_to_nothrow_swap;
+
+ bool have_is_nothrow_move = false;
+ bool have_is_nothrow_move_assign = false;
+ bool have_is_nothrow_swap = false;
+
+ UNORDERED_AUTO_TEST (check_is_nothrow_move) {
+ BOOST_TEST(
+ !boost::is_nothrow_move_constructible<hash_possible_exception>::value);
+ BOOST_TEST(
+ !boost::is_nothrow_move_assignable<hash_possible_exception>::value);
+ BOOST_TEST(!boost::is_nothrow_swappable<hash_possible_exception>::value);
+ BOOST_TEST((!boost::is_nothrow_move_constructible<
+ equal_to_nothrow<false, false, false> >::value));
+ BOOST_TEST((!boost::is_nothrow_move_assignable<
+ equal_to_nothrow<false, false, false> >::value));
+ BOOST_TEST((!boost::is_nothrow_swappable<
+ equal_to_nothrow<false, false, false> >::value));
+
+ have_is_nothrow_move =
+ boost::is_nothrow_move_constructible<hash_nothrow_move_construct>::value;
+ have_is_nothrow_move_assign =
+ boost::is_nothrow_move_assignable<hash_nothrow_move_assign>::value;
+ have_is_nothrow_swap =
+ boost::is_nothrow_swappable<hash_nothrow_swap>::value;
+
+// Check that the traits work when expected.
+#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && \
+ !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
+ BOOST_TEST(have_is_nothrow_move);
+ BOOST_TEST(have_is_nothrow_move_assign);
+#endif
+
+#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_NOEXCEPT) && \
+ !defined(BOOST_NO_CXX11_DECLTYPE) && \
+ !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ BOOST_TEST(have_is_nothrow_swap);
+#endif
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "have_is_nothrow_move: " << have_is_nothrow_move << std::endl
+ << "have_is_nothrow_swap: " << have_is_nothrow_swap << std::endl;
+ }
+
+ UNORDERED_AUTO_TEST (test_noexcept) {
+ if (have_is_nothrow_move) {
+ BOOST_TEST((boost::is_nothrow_move_constructible<
+ boost::unordered_set<int> >::value));
+ BOOST_TEST((boost::is_nothrow_move_constructible<
+ boost::unordered_multiset<int> >::value));
+ BOOST_TEST((boost::is_nothrow_move_constructible<
+ boost::unordered_map<int, int> >::value));
+ BOOST_TEST((boost::is_nothrow_move_constructible<
+ boost::unordered_multimap<int, int> >::value));
+ }
+
+ BOOST_TEST((!boost::is_nothrow_move_constructible<
+ boost::unordered_set<int, hash_possible_exception> >::value));
+ BOOST_TEST(
+ (!boost::is_nothrow_move_constructible<boost::unordered_multiset<int,
+ boost::hash<int>, equal_to_possible_exception> >::value));
+ }
+
+ UNORDERED_AUTO_TEST (test_nothrow_move_when_noexcept) {
+ typedef boost::unordered_set<int, hash_nothrow_move_construct,
+ equal_to_nothrow_move_construct>
+ throwing_set;
+
+ if (have_is_nothrow_move) {
+ BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
+ }
+
+ throwing_test_exception = false;
+
+ throwing_set x1;
+ x1.insert(10);
+ x1.insert(50);
+
+ try {
+ throwing_test_exception = true;
+
+ throwing_set x2 = boost::move(x1);
+ BOOST_TEST(x2.size() == 2);
+ BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
+ BOOST_TEST(have_is_nothrow_move);
+ } catch (test_exception) {
+ BOOST_TEST(!have_is_nothrow_move);
+ }
+
+ throwing_test_exception = false;
+ }
+
+ UNORDERED_AUTO_TEST (test_nothrow_move_assign_when_noexcept) {
+ typedef boost::unordered_set<int, hash_nothrow_move_assign,
+ equal_to_nothrow_move_assign>
+ throwing_set;
+
+ if (have_is_nothrow_move_assign) {
+ BOOST_TEST(boost::is_nothrow_move_assignable<throwing_set>::value);
+ }
+
+ throwing_test_exception = false;
+
+ throwing_set x1;
+ throwing_set x2;
+ x1.insert(10);
+ x1.insert(50);
+ for (int i = 0; i < 100; ++i) {
+ x2.insert(i);
+ }
+
+ try {
+ throwing_test_exception = true;
+
+ x2 = boost::move(x1);
+ BOOST_TEST(x2.size() == 2);
+ BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
+ BOOST_TEST(have_is_nothrow_move_assign);
+ } catch (test_exception) {
+ BOOST_TEST(!have_is_nothrow_move_assign);
+ }
+
+ throwing_test_exception = false;
+ }
+
+ UNORDERED_AUTO_TEST (test_nothrow_swap_when_noexcept) {
+ typedef boost::unordered_set<int, hash_nothrow_swap, equal_to_nothrow_swap>
+ throwing_set;
+
+ if (have_is_nothrow_swap) {
+ BOOST_TEST(boost::is_nothrow_swappable<throwing_set>::value);
+ }
+
+ throwing_test_exception = false;
+
+ throwing_set x1;
+ throwing_set x2;
+ x1.insert(10);
+ x1.insert(50);
+ for (int i = 0; i < 100; ++i) {
+ x2.insert(i);
+ }
+
+ try {
+ throwing_test_exception = true;
+
+ x1.swap(x2);
+ BOOST_TEST(x1.size() == 100);
+ BOOST_TEST(x2.size() == 2);
+ BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
+ BOOST_TEST(have_is_nothrow_swap);
+ } catch (test_exception) {
+ BOOST_TEST(!have_is_nothrow_swap);
+ }
+
+ throwing_test_exception = false;
+ }
+}
+
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/rehash_tests.cpp b/src/boost/libs/unordered/test/unordered/rehash_tests.cpp
new file mode 100644
index 000000000..65c089362
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/rehash_tests.cpp
@@ -0,0 +1,229 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/metafunctions.hpp"
+#include "../objects/test.hpp"
+
+namespace rehash_tests {
+
+ test::seed_t initialize_seed(2974);
+
+ template <class X> bool postcondition(X const& x, typename X::size_type n)
+ {
+ return static_cast<double>(x.bucket_count()) >=
+ static_cast<double>(x.size()) / x.max_load_factor() &&
+ x.bucket_count() >= n;
+ }
+
+ template <class X> void rehash_empty_test1(X*)
+ {
+ X x;
+
+ x.rehash(10000);
+ BOOST_TEST(postcondition(x, 10000));
+
+ x.rehash(0);
+ BOOST_TEST(postcondition(x, 0));
+
+ x.rehash(10000000);
+ BOOST_TEST(postcondition(x, 10000000));
+ }
+
+ template <class X>
+ void rehash_empty_test2(X*, test::random_generator generator)
+ {
+ test::random_values<X> v(1000, generator);
+ test::ordered<X> tracker;
+
+ X x;
+
+ x.rehash(10000);
+ BOOST_TEST(postcondition(x, 10000));
+
+ tracker.insert_range(v.begin(), v.end());
+ x.insert(v.begin(), v.end());
+ tracker.compare(x);
+
+ BOOST_TEST(postcondition(x, 10000));
+
+ x.rehash(10000000);
+ tracker.compare(x);
+ BOOST_TEST(postcondition(x, 10000000));
+ }
+
+ template <class X>
+ void rehash_empty_test3(X*, test::random_generator generator)
+ {
+ test::random_values<X> v(1000, generator);
+ test::ordered<X> tracker;
+
+ X x;
+
+ x.rehash(0);
+ BOOST_TEST(postcondition(x, 0));
+
+ tracker.insert_range(v.begin(), v.end());
+ x.insert(v.begin(), v.end());
+ tracker.compare(x);
+
+ BOOST_TEST(postcondition(x, 0));
+ }
+
+ template <class X> void rehash_test1(X*, test::random_generator generator)
+ {
+ test::random_values<X> v(1000, generator);
+ test::ordered<X> tracker;
+ tracker.insert_range(v.begin(), v.end());
+ X x(v.begin(), v.end());
+
+ x.rehash(0);
+ BOOST_TEST(postcondition(x, 0));
+ tracker.compare(x);
+
+ x.max_load_factor(0.25);
+ x.rehash(0);
+ BOOST_TEST(postcondition(x, 0));
+ tracker.compare(x);
+
+ x.max_load_factor(50.0);
+ x.rehash(0);
+ BOOST_TEST(postcondition(x, 0));
+ tracker.compare(x);
+
+ x.rehash(1000);
+ BOOST_TEST(postcondition(x, 1000));
+ tracker.compare(x);
+ }
+
+ template <class X> void reserve_empty_test1(X*)
+ {
+ X x;
+
+ x.reserve(10000);
+ BOOST_TEST(x.bucket_count() >= 10000);
+
+ x.reserve(0);
+
+ x.reserve(10000000);
+ BOOST_TEST(x.bucket_count() >= 10000000);
+ }
+
+ template <class X> void reserve_empty_test2(X*)
+ {
+ X x;
+ x.max_load_factor(0.25);
+
+ x.reserve(10000);
+ BOOST_TEST(x.bucket_count() >= 40000);
+
+ x.reserve(0);
+
+ x.reserve(10000000);
+ BOOST_TEST(x.bucket_count() >= 40000000);
+ }
+
+ template <class X> void reserve_test1(X*, test::random_generator generator)
+ {
+ for (int random_mlf = 0; random_mlf < 2; ++random_mlf) {
+ for (std::size_t i = 1; i < 2000; i += i < 50 ? 1 : 13) {
+ test::random_values<X> v(i, generator);
+
+ test::ordered<X> tracker;
+ tracker.insert_range(v.begin(), v.end());
+
+ X x;
+ x.max_load_factor(
+ random_mlf ? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
+ : 1.0f);
+ x.reserve(test::has_unique_keys<X>::value ? i : v.size());
+
+ // Insert an element before the range insert, otherwise there are
+ // no iterators to invalidate in the range insert, and it can
+ // rehash.
+ typename test::random_values<X>::iterator it = v.begin();
+ x.insert(*it);
+ ++it;
+
+ std::size_t bucket_count = x.bucket_count();
+ x.insert(it, v.end());
+ BOOST_TEST(bucket_count == x.bucket_count());
+ tracker.compare(x);
+ }
+ }
+ }
+
+ template <class X> void reserve_test2(X*, test::random_generator generator)
+ {
+ for (int random_mlf = 0; random_mlf < 2; ++random_mlf) {
+ for (std::size_t i = 0; i < 2000; i += i < 50 ? 1 : 13) {
+ test::random_values<X> v(i, generator);
+
+ test::ordered<X> tracker;
+ tracker.insert_range(v.begin(), v.end());
+
+ X x;
+ x.max_load_factor(
+ random_mlf ? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
+ : 1.0f);
+
+ x.reserve(test::has_unique_keys<X>::value ? i : v.size());
+
+ std::size_t bucket_count = x.bucket_count();
+ for (typename test::random_values<X>::iterator it = v.begin();
+ it != v.end(); ++it) {
+ x.insert(*it);
+ }
+
+ BOOST_TEST(bucket_count == x.bucket_count());
+ tracker.compare(x);
+ }
+ }
+ }
+
+ boost::unordered_set<int>* int_set_ptr;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_multiset_ptr;
+ boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
+ test::allocator2<test::movable> >* test_map_ptr;
+ boost::unordered_multimap<int, int>* int_multimap_ptr;
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_TEST(rehash_empty_test1,
+ ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
+ UNORDERED_TEST(rehash_empty_test2,
+ ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
+ (default_generator)(generate_collisions)(limited_range)))
+ UNORDERED_TEST(rehash_empty_test3,
+ ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
+ (default_generator)(generate_collisions)(limited_range)))
+ UNORDERED_TEST(rehash_test1,
+ ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
+ (default_generator)(generate_collisions)(limited_range)))
+ UNORDERED_TEST(reserve_empty_test1,
+ ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
+ UNORDERED_TEST(reserve_empty_test2,
+ ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
+ UNORDERED_TEST(reserve_test1,
+ ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
+ (default_generator)(generate_collisions)(limited_range)))
+ UNORDERED_TEST(reserve_test2,
+ ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
+ (default_generator)(generate_collisions)(limited_range)))
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/simple_tests.cpp b/src/boost/libs/unordered/test/unordered/simple_tests.cpp
new file mode 100644
index 000000000..d8a9ce413
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/simple_tests.cpp
@@ -0,0 +1,134 @@
+
+// Copyright 2006-2009 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)
+
+// This test checks the runtime requirements of containers.
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+#include <cstdlib>
+#include <algorithm>
+#include "../helpers/equivalent.hpp"
+
+template <class X> void simple_test(X const& a)
+{
+ test::unordered_equivalence_tester<X> equivalent(a);
+
+ {
+ X u;
+ BOOST_TEST(u.size() == 0);
+ BOOST_TEST(X().size() == 0);
+ }
+
+ {
+ BOOST_TEST(equivalent(X(a)));
+ }
+
+ {
+ X u(a);
+ BOOST_TEST(equivalent(u));
+ }
+
+ {
+ X u = a;
+ BOOST_TEST(equivalent(u));
+ }
+
+ {
+ X b(a);
+ BOOST_TEST(b.begin() == const_cast<X const&>(b).cbegin());
+ BOOST_TEST(b.end() == const_cast<X const&>(b).cend());
+ }
+
+ {
+ X b(a);
+ X c;
+ BOOST_TEST(equivalent(b));
+ BOOST_TEST(c.empty());
+ b.swap(c);
+ BOOST_TEST(b.empty());
+ BOOST_TEST(equivalent(c));
+ b.swap(c);
+ BOOST_TEST(c.empty());
+ BOOST_TEST(equivalent(b));
+ }
+
+ {
+ X u;
+ X& r = u;
+ BOOST_TEST(&(r = r) == &r);
+
+ BOOST_TEST(r.empty());
+ BOOST_TEST(&(r = a) == &r);
+ BOOST_TEST(equivalent(r));
+ BOOST_TEST(&(r = r) == &r);
+ BOOST_TEST(equivalent(r));
+ }
+
+ {
+ BOOST_TEST(a.size() == static_cast<typename X::size_type>(
+ std::distance(a.begin(), a.end())));
+ }
+
+ {
+ BOOST_TEST(a.empty() == (a.size() == 0));
+ }
+
+ {
+ BOOST_TEST(a.empty() == (a.begin() == a.end()));
+ X u;
+ BOOST_TEST(u.begin() == u.end());
+ }
+}
+
+UNORDERED_AUTO_TEST (simple_tests) {
+ using namespace std;
+ srand(14878);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
+ boost::unordered_set<int> set;
+ simple_test(set);
+
+ set.insert(1);
+ set.insert(2);
+ set.insert(1456);
+ simple_test(set);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
+ boost::unordered_multiset<int> multiset;
+ simple_test(multiset);
+
+ for (int i1 = 0; i1 < 1000; ++i1) {
+ int count = rand() % 10, index = rand();
+ for (int j = 0; j < count; ++j)
+ multiset.insert(index);
+ }
+ simple_test(multiset);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
+ boost::unordered_map<int, int> map;
+
+ for (int i2 = 0; i2 < 1000; ++i2) {
+ map.insert(std::pair<const int, int>(rand(), rand()));
+ }
+ simple_test(map);
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
+ boost::unordered_multimap<int, int> multimap;
+
+ for (int i3 = 0; i3 < 1000; ++i3) {
+ int count = rand() % 10, index = rand();
+ for (int j = 0; j < count; ++j)
+ multimap.insert(std::pair<const int, int>(index, rand()));
+ }
+ simple_test(multimap);
+}
+
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/swap_tests.cpp b/src/boost/libs/unordered/test/unordered/swap_tests.cpp
new file mode 100644
index 000000000..9a7106efc
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/swap_tests.cpp
@@ -0,0 +1,211 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include <boost/config.hpp>
+#include <algorithm>
+#include <iterator>
+#include "../helpers/test.hpp"
+#include "../objects/test.hpp"
+#include "../objects/cxx11_allocator.hpp"
+#include "../helpers/random_values.hpp"
+#include "../helpers/tracker.hpp"
+#include "../helpers/invariants.hpp"
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+namespace swap_tests {
+
+ test::seed_t initialize_seed(783472);
+
+ template <class X> void swap_test_impl(X& x1, X& x2)
+ {
+ test::ordered<X> tracker1 = test::create_ordered(x1);
+ test::ordered<X> tracker2 = test::create_ordered(x2);
+ tracker1.insert_range(x1.begin(), x1.end());
+ tracker2.insert_range(x2.begin(), x2.end());
+ x1.swap(x2);
+ tracker1.compare(x2);
+ tracker2.compare(x1);
+ }
+
+ template <class X> void swap_tests1(X*, test::random_generator generator)
+ {
+ {
+ test::check_instances check_;
+
+ X x;
+ swap_test_impl(x, x);
+ }
+
+ {
+ test::check_instances check_;
+
+ X x, y;
+ swap_test_impl(x, y);
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<X> v(1000, generator);
+ X x, y(v.begin(), v.end());
+ swap_test_impl(x, y);
+ swap_test_impl(x, y);
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<X> vx(1000, generator), vy(1000, generator);
+ X x(vx.begin(), vx.end()), y(vy.begin(), vy.end());
+ swap_test_impl(x, y);
+ swap_test_impl(x, y);
+ }
+ }
+
+ template <class X> void swap_tests2(X* ptr, test::random_generator generator)
+ {
+ swap_tests1(ptr, generator);
+
+ typedef typename X::hasher hasher;
+ typedef typename X::key_equal key_equal;
+ typedef typename X::allocator_type allocator_type;
+
+ {
+ test::check_instances check_;
+
+ X x(0, hasher(1), key_equal(1));
+ X y(0, hasher(2), key_equal(2));
+ swap_test_impl(x, y);
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<X> v(1000, generator);
+ X x(v.begin(), v.end(), 0, hasher(1), key_equal(1));
+ X y(0, hasher(2), key_equal(2));
+ swap_test_impl(x, y);
+ }
+
+ {
+ test::check_instances check_;
+
+ test::random_values<X> vx(100, generator), vy(50, generator);
+ X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1));
+ X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2));
+ swap_test_impl(x, y);
+ swap_test_impl(x, y);
+ }
+
+ {
+ test::force_equal_allocator force_(!allocator_type::is_propagate_on_swap);
+ test::check_instances check_;
+
+ test::random_values<X> vx(50, generator), vy(100, generator);
+ X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1));
+ X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
+
+ if (allocator_type::is_propagate_on_swap ||
+ x.get_allocator() == y.get_allocator()) {
+ swap_test_impl(x, y);
+ }
+ }
+
+ {
+ test::force_equal_allocator force_(!allocator_type::is_propagate_on_swap);
+ test::check_instances check_;
+
+ test::random_values<X> vx(100, generator), vy(100, generator);
+ X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1), allocator_type(1));
+ X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2), allocator_type(2));
+
+ if (allocator_type::is_propagate_on_swap ||
+ x.get_allocator() == y.get_allocator()) {
+ swap_test_impl(x, y);
+ swap_test_impl(x, y);
+ }
+ }
+ }
+
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ std::allocator<test::object> >* test_map_std_alloc;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_set;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::allocator2<test::object> >* test_multiset;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::allocator1<test::object> >* test_map;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::allocator2<test::object> >* test_multimap;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_swap> >*
+ test_set_prop_swap;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_swap> >*
+ test_multiset_prop_swap;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::propagate_swap> >*
+ test_map_prop_swap;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to, test::cxx11_allocator<test::object, test::propagate_swap> >*
+ test_multimap_prop_swap;
+
+ boost::unordered_set<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_swap> >*
+ test_set_no_prop_swap;
+ boost::unordered_multiset<test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_swap> >*
+ test_multiset_no_prop_swap;
+ boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_swap> >*
+ test_map_no_prop_swap;
+ boost::unordered_multimap<test::object, test::object, test::hash,
+ test::equal_to,
+ test::cxx11_allocator<test::object, test::no_propagate_swap> >*
+ test_multimap_no_prop_swap;
+
+ template <typename T> bool is_propagate(T*)
+ {
+ return T::allocator_type::is_propagate_on_swap;
+ }
+
+ using test::default_generator;
+ using test::generate_collisions;
+ using test::limited_range;
+
+ UNORDERED_AUTO_TEST (check_traits) {
+ BOOST_TEST(!is_propagate(test_set));
+ BOOST_TEST(is_propagate(test_set_prop_swap));
+ BOOST_TEST(!is_propagate(test_set_no_prop_swap));
+ }
+
+ UNORDERED_TEST(
+ swap_tests1, ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(
+ test_multimap)(test_set_prop_swap)(test_multiset_prop_swap)(
+ test_map_prop_swap)(test_multimap_prop_swap)(
+ test_set_no_prop_swap)(test_multiset_no_prop_swap)(
+ test_map_no_prop_swap)(test_multimap_no_prop_swap))(
+ (default_generator)(generate_collisions)(limited_range)))
+
+ UNORDERED_TEST(swap_tests2,
+ ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_swap)(
+ test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)(
+ test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(
+ test_multimap_no_prop_swap))(
+ (default_generator)(generate_collisions)(limited_range)))
+}
+RUN_TESTS()
diff --git a/src/boost/libs/unordered/test/unordered/unnecessary_copy_tests.cpp b/src/boost/libs/unordered/test/unordered/unnecessary_copy_tests.cpp
new file mode 100644
index 000000000..1c5ff4b7e
--- /dev/null
+++ b/src/boost/libs/unordered/test/unordered/unnecessary_copy_tests.cpp
@@ -0,0 +1,582 @@
+
+// Copyright 2006-2009 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)
+
+// clang-format off
+#include "../helpers/prefix.hpp"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+#include "../helpers/postfix.hpp"
+// clang-format on
+
+#include "../helpers/test.hpp"
+
+namespace unnecessary_copy_tests {
+ struct count_copies
+ {
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(count_copies)
+ public:
+ static int copies;
+ static int moves;
+ static int id_count;
+
+ count_copies() : tag_(0), id_(++id_count)
+ {
+ ++copies;
+ trace_op("Default construct");
+ }
+
+ explicit count_copies(int tag) : tag_(tag), id_(++id_count)
+ {
+ ++copies;
+ trace_op("Tag construct");
+ }
+
+ // This bizarre constructor is an attempt to confuse emplace.
+ //
+ // unordered_map<count_copies, count_copies> x:
+ // x.emplace(count_copies(1), count_copies(2));
+ // x.emplace(count_copies(1), count_copies(2), count_copies(3));
+ //
+ // The first emplace should use the single argument constructor twice.
+ // The second emplace should use the single argument contructor for
+ // the key, and this constructor for the value.
+ count_copies(count_copies const&, count_copies const& x)
+ : tag_(x.tag_), id_(++id_count)
+ {
+ ++copies;
+ trace_op("Pair construct");
+ }
+
+ count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count)
+ {
+ ++copies;
+ trace_op("Copy construct");
+ }
+
+ count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_), id_(++id_count)
+ {
+ x.tag_ = -1;
+ ++moves;
+ trace_op("Move construct");
+ }
+
+ count_copies& operator=(
+ BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
+ {
+ tag_ = p.tag_;
+ ++copies;
+ trace_op("Copy assign");
+ return *this;
+ }
+
+ count_copies& operator=(BOOST_RV_REF(count_copies) p) // Move assignment
+ {
+ tag_ = p.tag_;
+ ++moves;
+ trace_op("Move assign");
+ return *this;
+ }
+
+ ~count_copies() { trace_op("Destruct"); }
+
+ void trace_op(char const* str)
+ {
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_ << " (#" << id_
+ << ")" << std::endl;
+ }
+
+ int tag_;
+ int id_;
+ };
+
+ bool operator==(count_copies const& x, count_copies const& y)
+ {
+ return x.tag_ == y.tag_;
+ }
+
+ template <class T> T source() { return T(); }
+
+ void reset()
+ {
+ count_copies::copies = 0;
+ count_copies::moves = 0;
+
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\nReset\n" << std::endl;
+ }
+}
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+namespace boost
+#else
+namespace unnecessary_copy_tests
+#endif
+{
+ std::size_t hash_value(unnecessary_copy_tests::count_copies const& x)
+ {
+ return static_cast<std::size_t>(x.tag_);
+ }
+}
+
+// Boost.Move doesn't seem to work very well on this compiler.
+// For example for:
+//
+// T x;
+//
+// It will default construct T, and then move it in.
+// For 'T const' it seems to copy.
+
+#if defined(__IBMCPP__) && __IBMCPP__ <= 1210
+#define EXTRA_CONSTRUCT_COST 1
+#else
+#define EXTRA_CONSTRUCT_COST 0
+#endif
+
+#define COPY_COUNT(n) \
+ if (::unnecessary_copy_tests::count_copies::copies != n) { \
+ BOOST_ERROR("Wrong number of copies."); \
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
+ << "Number of copies: " \
+ << ::unnecessary_copy_tests::count_copies::copies << " expecting: " << n \
+ << std::endl; \
+ }
+#define MOVE_COUNT(n) \
+ if (::unnecessary_copy_tests::count_copies::moves != n) { \
+ BOOST_ERROR("Wrong number of moves."); \
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
+ << "Number of moves: " << ::unnecessary_copy_tests::count_copies::moves \
+ << " expecting: " << n << std::endl; \
+ }
+#define COPY_COUNT_RANGE(a, b) \
+ if (::unnecessary_copy_tests::count_copies::copies < a || \
+ ::unnecessary_copy_tests::count_copies::copies > b) { \
+ BOOST_ERROR("Wrong number of copies."); \
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
+ << "Number of copies: " \
+ << ::unnecessary_copy_tests::count_copies::copies << " expecting: [" \
+ << a << ", " << b << "]" << std::endl; \
+ }
+#define MOVE_COUNT_RANGE(a, b) \
+ if (::unnecessary_copy_tests::count_copies::moves < a || \
+ ::unnecessary_copy_tests::count_copies::moves > b) { \
+ BOOST_ERROR("Wrong number of moves."); \
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
+ << "Number of moves: " << ::unnecessary_copy_tests::count_copies::moves \
+ << " expecting: [" << a << ", " << b << "]" << std::endl; \
+ }
+#define COPY_COUNT_EXTRA(a, b) COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
+#define MOVE_COUNT_EXTRA(a, b) MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
+
+namespace unnecessary_copy_tests {
+ int count_copies::copies;
+ int count_copies::moves;
+ int count_copies::id_count;
+
+ template <class T> void unnecessary_copy_insert_test(T*)
+ {
+ T x;
+ typename T::value_type a;
+ reset();
+ x.insert(a);
+ COPY_COUNT(1);
+ MOVE_COUNT(0);
+ }
+
+ template <class T> void unnecessary_copy_insert_rvalue_set_test(T*)
+ {
+ T x;
+ typename T::value_type a;
+ reset();
+ x.insert(boost::move(a));
+ COPY_COUNT(0);
+ MOVE_COUNT(1);
+
+ typename T::value_type a2;
+ reset();
+ x.insert(boost::move(a));
+ COPY_COUNT(0);
+ MOVE_COUNT((x.size() == 2 ? 1 : 0));
+ }
+
+ template <class T> void unnecessary_copy_insert_rvalue_map_test(T*)
+ {
+ // Doesn't currently try to emulate std::pair move construction,
+ // so std::pair's require a copy. Could try emulating it in
+ // construct_from_args.
+
+ T x;
+ typename T::value_type a;
+ reset();
+ x.insert(boost::move(a));
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ COPY_COUNT(1);
+ MOVE_COUNT(0);
+#else
+ COPY_COUNT(0);
+ MOVE_COUNT(1);
+#endif
+
+ typename T::value_type a2;
+ reset();
+ x.insert(boost::move(a));
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ COPY_COUNT((x.size() == 2 ? 1 : 0));
+ MOVE_COUNT(0);
+#else
+ COPY_COUNT(0);
+ MOVE_COUNT((x.size() == 2 ? 1 : 0));
+#endif
+ }
+
+ boost::unordered_set<count_copies>* set;
+ boost::unordered_multiset<count_copies>* multiset;
+ boost::unordered_map<int, count_copies>* map;
+ boost::unordered_multimap<int, count_copies>* multimap;
+
+ UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap)))
+ UNORDERED_TEST(unnecessary_copy_insert_rvalue_set_test, ((set)(multiset)))
+ UNORDERED_TEST(unnecessary_copy_insert_rvalue_map_test, ((map)(multimap)))
+
+ template <class T> void unnecessary_copy_emplace_test(T*)
+ {
+ reset();
+ T x;
+ typename T::value_type a;
+ COPY_COUNT(1);
+ x.emplace(a);
+ COPY_COUNT(2);
+ }
+
+ template <class T> void unnecessary_copy_emplace_rvalue_test(T*)
+ {
+ reset();
+ T x;
+ x.emplace(source<typename T::value_type>());
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ COPY_COUNT(1);
+#else
+ COPY_COUNT(2);
+#endif
+ }
+
+ UNORDERED_TEST(
+ unnecessary_copy_emplace_test, ((set)(multiset)(map)(multimap)))
+ UNORDERED_TEST(
+ unnecessary_copy_emplace_rvalue_test, ((set)(multiset)(map)(multimap)))
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <class T> void unnecessary_copy_emplace_std_move_test(T*)
+ {
+ reset();
+ T x;
+ typename T::value_type a;
+ COPY_COUNT(1);
+ MOVE_COUNT(0);
+ x.emplace(std::move(a));
+ COPY_COUNT(1);
+ MOVE_COUNT(1);
+ }
+
+ UNORDERED_TEST(
+ unnecessary_copy_emplace_std_move_test, ((set)(multiset)(map)(multimap)))
+#endif
+
+ template <class T> void unnecessary_copy_emplace_boost_move_test(T*)
+ {
+ reset();
+ T x;
+ typename T::value_type a;
+ COPY_COUNT(1);
+ MOVE_COUNT_EXTRA(0, 1);
+ x.emplace(boost::move(a));
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ COPY_COUNT(1);
+ MOVE_COUNT(1);
+#else
+ // Since std::pair isn't movable, move only works for sets.
+ COPY_COUNT_RANGE(1, 2);
+ MOVE_COUNT_RANGE(0, 1);
+#endif
+ }
+
+ UNORDERED_TEST(
+ unnecessary_copy_emplace_boost_move_test, ((set)(multiset)(map)(multimap)))
+
+ template <class T> void unnecessary_copy_emplace_boost_move_set_test(T*)
+ {
+ reset();
+ T x;
+ typename T::value_type a;
+ COPY_COUNT(1);
+ MOVE_COUNT(0);
+ x.emplace(boost::move(a));
+ COPY_COUNT(1);
+ MOVE_COUNT(1);
+ }
+
+ UNORDERED_TEST(
+ unnecessary_copy_emplace_boost_move_set_test, ((set)(multiset)))
+
+ template <class T> void unnecessary_copy_emplace_boost_move_map_test(T*)
+ {
+ reset();
+ T x;
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+ typename T::value_type a;
+ COPY_COUNT(1);
+ MOVE_COUNT_EXTRA(0, 1);
+ x.emplace(boost::move(a));
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ COPY_COUNT(2);
+ MOVE_COUNT_EXTRA(0, 1);
+#else
+ COPY_COUNT(1);
+ MOVE_COUNT(1);
+#endif
+ }
+
+ UNORDERED_TEST(
+ unnecessary_copy_emplace_boost_move_map_test, ((map)(multimap)))
+
+ UNORDERED_AUTO_TEST (unnecessary_copy_emplace_set_test) {
+ // When calling 'source' the object is moved on some compilers, but not
+ // others. So count that here to adjust later.
+
+ reset();
+ source<count_copies>();
+ int source_cost = ::unnecessary_copy_tests::count_copies::moves;
+
+ //
+
+ reset();
+ boost::unordered_set<count_copies> x;
+ count_copies a;
+ x.insert(a);
+ COPY_COUNT(2);
+ MOVE_COUNT(0);
+
+//
+// 0 arguments
+//
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+ // The container will have to create a copy in order to compare with
+ // the existing element.
+ reset();
+ x.emplace();
+
+ // source_cost doesn't make much sense here, but it seems to fit.
+ COPY_COUNT(1);
+ MOVE_COUNT(source_cost);
+#endif
+
+ //
+ // 1 argument
+ //
+
+ // Emplace should be able to tell that there already is an element
+ // without creating a new one.
+ reset();
+ x.emplace(a);
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+
+ // A new object is created by source, but it shouldn't be moved or
+ // copied.
+ reset();
+ x.emplace(source<count_copies>());
+ COPY_COUNT(1);
+ MOVE_COUNT(source_cost);
+
+ // No move should take place.
+ reset();
+ x.emplace(boost::move(a));
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+
+ // Use a new value for cases where a did get moved...
+ count_copies b;
+
+ // The container will have to create a copy in order to compare with
+ // the existing element.
+ reset();
+ x.emplace(b.tag_);
+ COPY_COUNT(1);
+ MOVE_COUNT(0);
+
+ //
+ // 2 arguments
+ //
+
+ // The container will have to create b copy in order to compare with
+ // the existing element.
+ //
+ // Note to self: If copy_count == 0 it's an error not an optimization.
+ // TODO: Devise a better test.
+
+ reset();
+
+ x.emplace(b, b);
+ COPY_COUNT(1);
+ MOVE_COUNT(0);
+ }
+
+ UNORDERED_AUTO_TEST (unnecessary_copy_emplace_map_test) {
+ // When calling 'source' the object is moved on some compilers, but not
+ // others. So count that here to adjust later.
+
+ reset();
+ source<count_copies>();
+ int source_cost = ::unnecessary_copy_tests::count_copies::moves;
+
+ reset();
+ source<std::pair<count_copies, count_copies> >();
+ int source_pair_cost = ::unnecessary_copy_tests::count_copies::moves;
+
+ //
+
+ reset();
+ boost::unordered_map<count_copies, count_copies> x;
+ // TODO: Run tests for pairs without const etc.
+ std::pair<count_copies const, count_copies> a;
+ x.emplace(a);
+ COPY_COUNT_EXTRA(4, 1);
+ MOVE_COUNT_EXTRA(0, 1);
+
+//
+// 0 arguments
+//
+
+#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
+ // COPY_COUNT(1) would be okay here.
+ reset();
+ x.emplace();
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
+ // This is a little odd, Visual C++ 11 seems to move the pair, which
+ // results in one copy (for the const key) and one move (for the
+ // non-const mapped value). Since 'emplace(boost::move(a))' (see below)
+ // has the normal result, it must be some odd consequence of how
+ // Visual C++ 11 handles calling move for default arguments.
+ COPY_COUNT(3);
+ MOVE_COUNT(1);
+#else
+ COPY_COUNT_EXTRA(2, 1);
+ MOVE_COUNT_EXTRA(0, 1);
+#endif
+#endif
+
+ reset();
+ x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
+ boost::make_tuple());
+ COPY_COUNT(2);
+ MOVE_COUNT(0);
+
+ //
+ // 1 argument
+ //
+
+ reset();
+ x.emplace(a);
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+
+ // A new object is created by source, but it shouldn't be moved or
+ // copied.
+ reset();
+ x.emplace(source<std::pair<count_copies, count_copies> >());
+ COPY_COUNT(2);
+ MOVE_COUNT(source_pair_cost);
+
+#if !(defined(__GNUC__) && __cplusplus < 199900L) && \
+ !(defined(_MSC_VER) && _MSC_VER < 1600)
+ count_copies part;
+ reset();
+ std::pair<count_copies const&, count_copies const&> a_ref(part, part);
+ x.emplace(a_ref);
+ COPY_COUNT(2);
+ MOVE_COUNT(0);
+
+#endif
+
+ // No move should take place.
+ // (since a is already in the container)
+ reset();
+ x.emplace(boost::move(a));
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+
+ //
+ // 2 arguments
+ //
+
+ std::pair<count_copies const, count_copies> b;
+
+ reset();
+ x.emplace(b.first, b.second);
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+
+ reset();
+ x.emplace(source<count_copies>(), source<count_copies>());
+ COPY_COUNT(2);
+ MOVE_COUNT(source_cost * 2);
+
+ // source<count_copies> creates a single copy.
+ reset();
+ x.emplace(b.first, source<count_copies>());
+ COPY_COUNT(1);
+ MOVE_COUNT(source_cost);
+
+ reset();
+ x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
+ COPY_COUNT(2);
+ MOVE_COUNT(0);
+
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ boost::make_tuple(boost::ref(b.first)),
+ boost::make_tuple(boost::ref(b.second)));
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+
+#if BOOST_UNORDERED_TUPLE_ARGS
+
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::make_tuple(std::ref(b.first)), std::make_tuple(std::ref(b.second)));
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+
+ std::pair<count_copies const, count_copies> move_source_trial;
+ reset();
+ std::make_tuple(std::move(move_source_trial.first));
+ std::make_tuple(std::move(move_source_trial.second));
+ int tuple_move_cost = ::unnecessary_copy_tests::count_copies::moves;
+ int tuple_copy_cost = ::unnecessary_copy_tests::count_copies::copies;
+
+ std::pair<count_copies const, count_copies> move_source;
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::make_tuple(std::move(move_source.first)),
+ std::make_tuple(std::move(move_source.second)));
+ COPY_COUNT(tuple_copy_cost);
+ MOVE_COUNT(tuple_move_cost);
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
+ !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
+ !(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
+ reset();
+ x.emplace(boost::unordered::piecewise_construct,
+ std::forward_as_tuple(b.first), std::forward_as_tuple(b.second));
+ COPY_COUNT(0);
+ MOVE_COUNT(0);
+#endif
+
+#endif
+ }
+}
+
+RUN_TESTS()