From ecd5b239a4b573899b6e0189d69d095b17f818d7 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 29 Nov 2017 23:31:21 +0000 Subject: [PATCH 01/50] Use appropriate snapshot when testing on travis --- .travis.yml | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 14c0168a..7b929e7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,20 +45,54 @@ before_install: - if [ -n $enable_coverage ]; then pip install --user cpp-coveralls; fi before_script: + - export BOOST_VERSION=1.64.0 + - export BOOST_FILENAME=boost_1_64_0 + - export BOOST_ROOT=${HOME}/boost - cd ${TRAVIS_BUILD_DIR} - touch Jamroot.jam - cd $HOME - echo $user_config > ~/user-config.jam - cat ~/user-config.jam - - wget -O boost.tar.bz2 https://dl.bintray.com/boostorg/release/1.64.0/source/boost_1_64_0.tar.bz2 - - tar -xjf boost.tar.bz2 - - mv boost_1_64_0 boost - - rm -r boost/boost/unordered + - | + # Pick snapshot to use + if [ "$TRAVIS_EVENT_TYPE" == "cron" ] + then + if [ "$TRAVIS_BRANCH" == "master" ] + then + snapshot=master + else + snapshot=develop + fi + else + snapshot=stable + fi + + # Set download_url for snapshot + if [ $snapshot == "stable" ] + then + download_url=https://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/${BOOST_FILENAME}.tar.bz2/download + else + download_url=$(curl https://api.bintray.com/packages/boostorg/$snapshot/snapshot/files | + python -c "import os.path, sys, json; x = json.load(sys.stdin); print '\n'.join(a['path'] for a in x if os.path.splitext(a['path'])[1] == '.bz2')" | + head -n 1 | + sed "s/^/http:\/\/dl.bintray.com\/boostorg\/$snapshot\//") + fi + + # Download and extract snapshot + echo "Downloading ${download_url}" + mkdir $HOME/download + mkdir $HOME/extract + cd $HOME/download + wget -O boost.tar.bz2 $download_url + cd $HOME/extract + tar -xjf $HOME/download/boost.tar.bz2 + mv * ${BOOST_ROOT} + - rm -r ${BOOST_ROOT}/boost/unordered after_success: if [ -n $enable_coverage ]; then coveralls -r ${TRAVIS_BUILD_DIR} -b ${TRAVIS_BUILD_DIR}/test --gcov-options '\-lp' --include include/boost/unordered/ ; fi script: - cd ${TRAVIS_BUILD_DIR}/test - - bjam -q include=${HOME}/boost include=${TRAVIS_BUILD_DIR}/include + - bjam -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include - xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml From 9bb861acccfa3ae4cb86a8243ab0790b3afa7d86 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 1 Dec 2017 08:11:36 +0000 Subject: [PATCH 02/50] Use std::advance in test::next, and use it instead of boost::next Mainly to avoid warnings from boost::next --- test/helpers/helpers.hpp | 10 ++++++---- test/unordered/extract_tests.cpp | 9 ++++----- test/unordered/merge_tests.cpp | 9 ++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/helpers/helpers.hpp b/test/helpers/helpers.hpp index 5f816cfe..e34bf259 100644 --- a/test/helpers/helpers.hpp +++ b/test/helpers/helpers.hpp @@ -6,6 +6,8 @@ #if !defined(BOOST_UNORDERED_TEST_HELPERS_HEADER) #define BOOST_UNORDERED_TEST_HELPERS_HEADER +#include + namespace test { template struct get_key_impl { @@ -36,16 +38,16 @@ namespace test { // test::next // // Increments an iterator by 1 or a given value. - // Like boost::next, but simpler and slower. + // Like boost::next, but simpler. + // Mainly because boost::next uses an MPL file + // which causes warnings. template Iterator next(Iterator it) { return ++it; } template Iterator next(Iterator it, IntType x) { - for (; x > 0; --x) { - ++it; - } + std::advance(it, x); return it; } } diff --git a/test/unordered/extract_tests.cpp b/test/unordered/extract_tests.cpp index ae305881..3bbe51d2 100644 --- a/test/unordered/extract_tests.cpp +++ b/test/unordered/extract_tests.cpp @@ -17,7 +17,6 @@ #include "../helpers/test.hpp" #include "../helpers/tracker.hpp" #include "../objects/test.hpp" -#include namespace extract_tests { @@ -94,10 +93,10 @@ namespace extract_tests { if (index == 0) { prev = pos = x.begin(); } else { - prev = boost::next(x.begin(), index - 1); - pos = boost::next(prev); + prev = test::next(x.begin(), index - 1); + pos = test::next(prev); } - next = boost::next(pos); + next = test::next(pos); BOOST_DEDUCED_TYPENAME Container::key_type key = test::get_key(*pos); std::size_t count = x.count(key); @@ -106,7 +105,7 @@ namespace extract_tests { --size; if (size > 0) BOOST_TEST( - index == 0 ? next == x.begin() : next == boost::next(prev)); + 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) diff --git a/test/unordered/merge_tests.cpp b/test/unordered/merge_tests.cpp index 3c27b745..897abb34 100644 --- a/test/unordered/merge_tests.cpp +++ b/test/unordered/merge_tests.cpp @@ -15,7 +15,6 @@ #include "../helpers/test.hpp" #include "../helpers/tracker.hpp" #include "../objects/test.hpp" -#include namespace merge_tests { @@ -174,8 +173,8 @@ namespace merge_tests { test::random_values v1(1000, generator); test::random_values v2(1000, generator); - v1.insert(v2.begin(), boost::next(v2.begin(), 100)); - v2.insert(v1.begin(), boost::next(v1.begin(), 100)); + 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)); @@ -207,8 +206,8 @@ namespace merge_tests { test::random_values v1(1000, generator); test::random_values v2(1000, generator); - v1.insert(v2.begin(), boost::next(v2.begin(), 100)); - v2.insert(v1.begin(), boost::next(v1.begin(), 100)); + 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)); From c037169e1ad36b9ed755cc622876fd5a6c87e059 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 3 Dec 2017 14:11:34 +0000 Subject: [PATCH 03/50] Update paths for headers moved from detail --- doc/src_code/dictionary.cpp | 2 +- doc/src_code/point1.cpp | 2 +- doc/src_code/point2.cpp | 2 +- examples/case_insensitive_test.cpp | 2 +- include/boost/unordered/detail/implementation.hpp | 2 +- test/helpers/count.hpp | 2 +- test/helpers/equivalent.hpp | 2 +- test/helpers/test.hpp | 2 +- test/unordered/allocator_traits.cpp | 2 +- test/unordered/extract_tests.cpp | 3 +-- test/unordered/minimal_allocator.cpp | 2 +- 11 files changed, 11 insertions(+), 12 deletions(-) diff --git a/doc/src_code/dictionary.cpp b/doc/src_code/dictionary.cpp index dece3089..4e080003 100644 --- a/doc/src_code/dictionary.cpp +++ b/doc/src_code/dictionary.cpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include #include #include "../../examples/fnv1.hpp" diff --git a/doc/src_code/point1.cpp b/doc/src_code/point1.cpp index dd562264..23ed0a58 100644 --- a/doc/src_code/point1.cpp +++ b/doc/src_code/point1.cpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include //[point_example1 struct point { diff --git a/doc/src_code/point2.cpp b/doc/src_code/point2.cpp index 359984cb..b012ca3c 100644 --- a/doc/src_code/point2.cpp +++ b/doc/src_code/point2.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include //[point_example2 struct point { diff --git a/examples/case_insensitive_test.cpp b/examples/case_insensitive_test.cpp index ee1ed8da..b717c130 100644 --- a/examples/case_insensitive_test.cpp +++ b/examples/case_insensitive_test.cpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "./case_insensitive.hpp" -#include +#include #include struct word_info { diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index d25026fe..7a9e4761 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -13,7 +13,7 @@ #endif #include -#include +#include #include #include #include diff --git a/test/helpers/count.hpp b/test/helpers/count.hpp index 3ed49ed6..90372dca 100644 --- a/test/helpers/count.hpp +++ b/test/helpers/count.hpp @@ -6,7 +6,7 @@ #if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD) #define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD -#include +#include namespace test { struct object_count diff --git a/test/helpers/equivalent.hpp b/test/helpers/equivalent.hpp index 6d05f204..5c1bfa82 100644 --- a/test/helpers/equivalent.hpp +++ b/test/helpers/equivalent.hpp @@ -10,7 +10,7 @@ #include "./list.hpp" #include "./metafunctions.hpp" #include -#include +#include #include #include diff --git a/test/helpers/test.hpp b/test/helpers/test.hpp index 1acd6d77..5534f811 100644 --- a/test/helpers/test.hpp +++ b/test/helpers/test.hpp @@ -6,7 +6,7 @@ #if !defined(BOOST_UNORDERED_TEST_TEST_HEADER) #define BOOST_UNORDERED_TEST_TEST_HEADER -#include +#include #include #include diff --git a/test/unordered/allocator_traits.cpp b/test/unordered/allocator_traits.cpp index 9b8738c2..f59fc876 100644 --- a/test/unordered/allocator_traits.cpp +++ b/test/unordered/allocator_traits.cpp @@ -3,7 +3,7 @@ // 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 +#include #include #include #include diff --git a/test/unordered/extract_tests.cpp b/test/unordered/extract_tests.cpp index 3bbe51d2..aef7fb4e 100644 --- a/test/unordered/extract_tests.cpp +++ b/test/unordered/extract_tests.cpp @@ -104,8 +104,7 @@ namespace extract_tests { BOOST_TEST(n); --size; if (size > 0) - BOOST_TEST( - index == 0 ? next == x.begin() : next == test::next(prev)); + 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) diff --git a/test/unordered/minimal_allocator.cpp b/test/unordered/minimal_allocator.cpp index f80002ca..a692443e 100644 --- a/test/unordered/minimal_allocator.cpp +++ b/test/unordered/minimal_allocator.cpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "../objects/test.hpp" -#include +#include #include #include #include From 311e126ac403d98efed14ae8893c1cca7260957f Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 3 Dec 2017 18:45:00 +0000 Subject: [PATCH 04/50] Remove dependency on iterator --- .../boost/unordered/detail/implementation.hpp | 8 +- test/helpers/input_iterator.hpp | 23 +++-- test/unordered/compile_tests.hpp | 83 +++++++++---------- 3 files changed, 55 insertions(+), 59 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 7a9e4761..fb1d4788 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -33,8 +32,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -244,9 +243,8 @@ namespace boost { // iterator SFINAE template - struct is_forward - : boost::is_convertible::type, - boost::forward_traversal_tag> + struct is_forward : boost::is_base_of::iterator_category> { }; diff --git a/test/helpers/input_iterator.hpp b/test/helpers/input_iterator.hpp index 18e6695d..b32dbb37 100644 --- a/test/helpers/input_iterator.hpp +++ b/test/helpers/input_iterator.hpp @@ -7,7 +7,6 @@ #define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER #include -#include #include namespace test { @@ -28,12 +27,12 @@ namespace test { template struct input_iterator_adaptor : public std::iterator::type, + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type, std::ptrdiff_t, - BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type, + BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer, proxy > { - typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type value_type; input_iterator_adaptor() : base_() {} @@ -68,17 +67,17 @@ namespace test { template struct copy_iterator_adaptor - : public std::iterator< - BOOST_DEDUCED_TYPENAME boost::iterator_category::type, - BOOST_DEDUCED_TYPENAME boost::iterator_value::type, - BOOST_DEDUCED_TYPENAME boost::iterator_difference::type, - BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type, + : public std::iterator::iterator_category, + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type, + BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type, + BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer, proxy > { - typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type value_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference::type - difference_type; + typedef BOOST_DEDUCED_TYPENAME + std::iterator_traits::difference_type difference_type; copy_iterator_adaptor() : base_() {} explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {} diff --git a/test/unordered/compile_tests.hpp b/test/unordered/compile_tests.hpp index 0a6176ad..c3aa9a87 100644 --- a/test/unordered/compile_tests.hpp +++ b/test/unordered/compile_tests.hpp @@ -17,7 +17,6 @@ #endif #include "../helpers/check_return_type.hpp" -#include #include #include #include @@ -56,14 +55,14 @@ template void container_test(X& r, T const&) typedef BOOST_DEDUCED_TYPENAME X::difference_type difference_type; typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type iterator_value_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type - const_iterator_value_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference::type + typedef BOOST_DEDUCED_TYPENAME + std::iterator_traits::value_type const_iterator_value_type; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type iterator_difference_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference< - const_iterator>::type const_iterator_difference_type; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_iterator>::difference_type const_iterator_difference_type; typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; typedef BOOST_DEDUCED_TYPENAME X::reference reference; @@ -263,14 +262,14 @@ template void unordered_set_test(X& r, Key const&) typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer const_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer< - const_local_iterator>::type const_local_iterator_pointer; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_local_iterator>::pointer const_local_iterator_pointer; BOOST_STATIC_ASSERT( (boost::is_same::value)); @@ -309,14 +308,14 @@ void unordered_map_test(X& r, Key const& k, T const& v) typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer const_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer< - const_local_iterator>::type const_local_iterator_pointer; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_local_iterator>::pointer const_local_iterator_pointer; BOOST_STATIC_ASSERT((boost::is_same::value)); BOOST_STATIC_ASSERT( @@ -482,41 +481,41 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq) typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; - typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY::type - iterator_category; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference::type + typedef BOOST_DEDUCED_TYPENAME + std::iterator_traits::iterator_category iterator_category; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type iterator_difference; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::reference iterator_reference; - typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY< - local_iterator>::type local_iterator_category; - typedef BOOST_DEDUCED_TYPENAME - boost::iterator_difference::type local_iterator_difference; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + local_iterator>::iterator_category local_iterator_category; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + local_iterator>::difference_type local_iterator_difference; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::reference local_iterator_reference; - typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY< - const_iterator>::type const_iterator_category; - typedef BOOST_DEDUCED_TYPENAME - boost::iterator_difference::type const_iterator_difference; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_iterator>::iterator_category const_iterator_category; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_iterator>::difference_type const_iterator_difference; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer const_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference::type + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::reference const_iterator_reference; - typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY< - const_local_iterator>::type const_local_iterator_category; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference< - const_local_iterator>::type const_local_iterator_difference; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer< - const_local_iterator>::type const_local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference< - const_local_iterator>::type const_local_iterator_reference; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_local_iterator>::iterator_category const_local_iterator_category; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_local_iterator>::difference_type const_local_iterator_difference; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_local_iterator>::pointer const_local_iterator_pointer; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< + const_local_iterator>::reference const_local_iterator_reference; typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; BOOST_STATIC_ASSERT((boost::is_same::value)); From c2b9b22f67608ac9ece084db2c35d29d386fb3c0 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 19 Dec 2017 12:10:53 +0000 Subject: [PATCH 05/50] Use 1.66.0 in tests --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7b929e7e..96f79e8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,8 +45,8 @@ before_install: - if [ -n $enable_coverage ]; then pip install --user cpp-coveralls; fi before_script: - - export BOOST_VERSION=1.64.0 - - export BOOST_FILENAME=boost_1_64_0 + - export BOOST_VERSION=1.66.0 + - export BOOST_FILENAME=boost_1_66_0 - export BOOST_ROOT=${HOME}/boost - cd ${TRAVIS_BUILD_DIR} - touch Jamroot.jam From 6327d174d2ffc540ff4040a5d20ea24463083c46 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 19 Dec 2017 12:11:35 +0000 Subject: [PATCH 06/50] Test C++17 mode in travis --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 96f79e8f..becacec7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,10 @@ matrix: env: | label="gcc 32 bit C++11"; user_config="using gcc : : g++-4.8 -m32 -fsanitize=address -Werror --std=c++11 ;" + - compiler: clang + env: | + label="clang C++17"; + user_config="using clang : : clang++ -fsanitize=address -Werror --std=c++17 ;" - compiler: clang env: | label="clang C++11"; From f99dee19178eda18e15b9923e8bad366095d4f63 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 19 Dec 2017 12:11:36 +0000 Subject: [PATCH 07/50] Use predef for detecting piecewise construction And detect it for recent dinkumware. --- include/boost/unordered/detail/fwd.hpp | 13 +++++++++---- include/boost/unordered/detail/implementation.hpp | 1 - 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/boost/unordered/detail/fwd.hpp b/include/boost/unordered/detail/fwd.hpp index 75030a9a..e749ce67 100644 --- a/include/boost/unordered/detail/fwd.hpp +++ b/include/boost/unordered/detail/fwd.hpp @@ -11,6 +11,8 @@ #pragma once #endif +#include + #if defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT) // Already defined. #elif defined(BOOST_LIBSTDCXX11) @@ -18,16 +20,19 @@ #if BOOST_LIBSTDCXX_VERSION > 40600 #define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 #endif -#elif defined(_LIBCPP_VERSION) +#elif BOOST_LIB_STD_CXX // https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206 -#if _LIBCPP_VERSION >= 3000 +#if BOOST_LIB_STD_CXX >= BOOST_VERSION_NUMBER(3, 0, 0) #define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 #endif -#elif defined(BOOST_MSVC) +#elif defined(BOOST_LIB_STD_DINKUMWARE) // Apparently C++11 standard supported in Visual Studio 2012 // https://msdn.microsoft.com/en-us/library/hh567368.aspx#stl // 2012 = VC+11 = BOOST_MSVC 1700 Hopefully! -#if BOOST_MSVC >= 1700 +// I have no idea when Dinkumware added it, probably a lot +// earlier than this check. +#if BOOST_LIB_STD_DINKUMWARE >= BOOST_VERSION_NUMBER(6, 50, 0) || \ + BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(17, 0, 0) #define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 #endif #endif diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index fb1d4788..77d55b1d 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include From b50e0d610f96780d5551bcdc20bf1028a09f7536 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 19 Dec 2017 12:11:36 +0000 Subject: [PATCH 08/50] Initial implementation of template deduction guides --- .../boost/unordered/detail/implementation.hpp | 12 + include/boost/unordered/unordered_map.hpp | 142 +++++++ include/boost/unordered/unordered_set.hpp | 95 +++++ test/Jamfile.v2 | 1 + test/unordered/deduction_tests.cpp | 347 ++++++++++++++++++ 5 files changed, 597 insertions(+) create mode 100644 test/unordered/deduction_tests.cpp diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 77d55b1d..c5d143ea 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -193,6 +193,18 @@ #endif #endif +// BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES + +#if !defined(BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES) +#if BOOST_COMP_CLANG && __cplusplus >= 201703 +#define BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES 1 +#endif +#endif + +#if !defined(BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES) +#define BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES 0 +#endif + namespace boost { namespace unordered { namespace iterator_detail { diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index bae3aa2f..e32f6123 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -831,6 +831,81 @@ namespace boost { #endif }; // class template unordered_map +#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES + + namespace detail { + template + using iter_key_t = + typename std::iterator_traits::value_type::first_type; + template + using iter_val_t = + typename std::iterator_traits::value_type::second_type; + template + using iter_to_alloc_t = + typename std::pair const, iter_val_t >; + } + + template >, + class Pred = + std::equal_to >, + class Allocator = std::allocator< + boost::unordered::detail::iter_to_alloc_t > > + unordered_map(InputIterator, InputIterator, + std::size_t = boost::unordered::detail::default_bucket_count, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + ->unordered_map, + boost::unordered::detail::iter_val_t, Hash, Pred, + Allocator>; + + template , + class Pred = std::equal_to, + class Allocator = std::allocator > > + unordered_map(std::initializer_list >, + std::size_t = boost::unordered::detail::default_bucket_count, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + ->unordered_map; + + template + unordered_map(InputIterator, InputIterator, std::size_t, Allocator) + ->unordered_map, + boost::unordered::detail::iter_val_t, + boost::hash >, + std::equal_to >, + Allocator>; + + template + unordered_map(InputIterator, InputIterator, Allocator) + ->unordered_map, + boost::unordered::detail::iter_val_t, + boost::hash >, + std::equal_to >, + Allocator>; + + template + unordered_map(InputIterator, InputIterator, std::size_t, Hash, Allocator) + ->unordered_map, + boost::unordered::detail::iter_val_t, Hash, + std::equal_to >, + Allocator>; + + template + unordered_map( + std::initializer_list >, std::size_t, Allocator) + ->unordered_map, std::equal_to, Allocator>; + + template + unordered_map(std::initializer_list >, Allocator) + ->unordered_map, std::equal_to, Allocator>; + + template + unordered_map(std::initializer_list >, std::size_t, + Hash, Allocator) + ->unordered_map, Allocator>; + +#endif + template class unordered_multimap { @@ -1363,6 +1438,73 @@ namespace boost { #endif }; // class template unordered_multimap +#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES + + template >, + class Pred = + std::equal_to >, + class Allocator = std::allocator< + boost::unordered::detail::iter_to_alloc_t > > + unordered_multimap(InputIterator, InputIterator, + std::size_t = boost::unordered::detail::default_bucket_count, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + ->unordered_multimap, + boost::unordered::detail::iter_val_t, Hash, Pred, + Allocator>; + + template , + class Pred = std::equal_to, + class Allocator = std::allocator > > + unordered_multimap(std::initializer_list >, + std::size_t = boost::unordered::detail::default_bucket_count, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + ->unordered_multimap; + + template + unordered_multimap(InputIterator, InputIterator, std::size_t, Allocator) + ->unordered_multimap, + boost::unordered::detail::iter_val_t, + boost::hash >, + std::equal_to >, + Allocator>; + + template + unordered_multimap(InputIterator, InputIterator, Allocator) + ->unordered_multimap, + boost::unordered::detail::iter_val_t, + boost::hash >, + std::equal_to >, + Allocator>; + + template + unordered_multimap( + InputIterator, InputIterator, std::size_t, Hash, Allocator) + ->unordered_multimap, + boost::unordered::detail::iter_val_t, Hash, + std::equal_to >, + Allocator>; + + template + unordered_multimap( + std::initializer_list >, std::size_t, Allocator) + ->unordered_multimap, std::equal_to, + Allocator>; + + template + unordered_multimap( + std::initializer_list >, Allocator) + ->unordered_multimap, std::equal_to, + Allocator>; + + template + unordered_multimap(std::initializer_list >, + std::size_t, Hash, Allocator) + ->unordered_multimap, Allocator>; + +#endif + //////////////////////////////////////////////////////////////////////////// template diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index e01c5586..bbd243d0 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -545,6 +545,52 @@ namespace boost { #endif }; // class template unordered_set +#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES + + template ::value_type>, + class Pred = + std::equal_to::value_type>, + class Allocator = std::allocator< + typename std::iterator_traits::value_type> > + unordered_set(InputIterator, InputIterator, + std::size_t = boost::unordered::detail::default_bucket_count, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + ->unordered_set::value_type, + Hash, Pred, Allocator>; + + template , + class Pred = std::equal_to, class Allocator = std::allocator > + unordered_set(std::initializer_list, + std::size_t = boost::unordered::detail::default_bucket_count, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + ->unordered_set; + + template + unordered_set(InputIterator, InputIterator, std::size_t, Allocator) + ->unordered_set::value_type, + boost::hash::value_type>, + std::equal_to::value_type>, + Allocator>; + + template + unordered_set(InputIterator, InputIterator, std::size_t, Hash, Allocator) + ->unordered_set::value_type, + Hash, + std::equal_to::value_type>, + Allocator>; + + template + unordered_set(std::initializer_list, std::size_t, Allocator) + ->unordered_set, std::equal_to, Allocator>; + + template + unordered_set(std::initializer_list, std::size_t, Hash, Allocator) + ->unordered_set, Allocator>; + +#endif + template class unordered_multiset { #if defined(BOOST_UNORDERED_USE_MOVE) @@ -1049,6 +1095,55 @@ namespace boost { #endif }; // class template unordered_multiset +#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES + + template ::value_type>, + class Pred = + std::equal_to::value_type>, + class Allocator = std::allocator< + typename std::iterator_traits::value_type> > + unordered_multiset(InputIterator, InputIterator, + std::size_t = boost::unordered::detail::default_bucket_count, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + ->unordered_multiset< + typename std::iterator_traits::value_type, Hash, Pred, + Allocator>; + + template , + class Pred = std::equal_to, class Allocator = std::allocator > + unordered_multiset(std::initializer_list, + std::size_t = boost::unordered::detail::default_bucket_count, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + ->unordered_multiset; + + template + unordered_multiset(InputIterator, InputIterator, std::size_t, Allocator) + ->unordered_multiset< + typename std::iterator_traits::value_type, + boost::hash::value_type>, + std::equal_to::value_type>, + Allocator>; + + template + unordered_multiset( + InputIterator, InputIterator, std::size_t, Hash, Allocator) + ->unordered_multiset< + typename std::iterator_traits::value_type, Hash, + std::equal_to::value_type>, + Allocator>; + + template + unordered_multiset(std::initializer_list, std::size_t, Allocator) + ->unordered_multiset, std::equal_to, Allocator>; + + template + unordered_multiset(std::initializer_list, std::size_t, Hash, Allocator) + ->unordered_multiset, Allocator>; + +#endif + //////////////////////////////////////////////////////////////////////////// template unordered_set::unordered_set() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e06b569f..67c31d98 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -63,6 +63,7 @@ test-suite unordered [ 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 : : : BOOST_UNORDERED_USE_MOVE diff --git a/test/unordered/deduction_tests.cpp b/test/unordered/deduction_tests.cpp new file mode 100644 index 00000000..f1e14c94 --- /dev/null +++ b/test/unordered/deduction_tests.cpp @@ -0,0 +1,347 @@ +#include +#include +#include + +#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES +struct hash_equals +{ + template bool operator()(T const& x) const + { + boost::hash hf; + return hf(x); + } + + template bool operator()(T const& x, T const& y) const + { + std::equal_to eq; + return eq(x, y); + } +}; + +template struct test_allocator +{ + typedef T value_type; + test_allocator() = default; + template test_allocator(test_allocator 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 > x; + x.push_back(std::make_pair(1, 3)); + x.push_back(std::make_pair(5, 10)); + test_allocator > pair_allocator; + hash_equals f; + + // unordered_map + + /* + template>, + class Pred = equal_to>, + class Allocator = allocator>> + unordered_map(InputIterator, InputIterator, typename see below::size_type = + see below, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_map, iter_val_t, + Hash, Pred, + Allocator>; + */ + + { + boost::unordered_map m(x.begin(), x.end()); + static_assert( + std::is_same >::value); + } + + /* Ambiguous: + { + boost::unordered_map m(x.begin(), x.end(), 0, std::hash()); + static_assert(std::is_same>>::value); + } + + { + boost::unordered_map m(x.begin(), x.end(), 0, std::hash(), + std::equal_to()); + static_assert(std::is_same, std::equal_to>>::value); + } + */ + + { + boost::unordered_map m(x.begin(), x.end(), 0, std::hash(), + std::equal_to(), pair_allocator); + static_assert(std::is_same, std::equal_to, + test_allocator > > >::value); + } + + /* + template, + class Pred = equal_to, class Allocator = allocator>> + unordered_map(initializer_list>, + typename see below::size_type = see below, Hash = Hash(), + Pred = Pred(), Allocator = Allocator()) + -> unordered_map; + */ + + { + boost::unordered_map m({std::pair(1, 2)}); + static_assert( + std::is_same >::value); + } + + /* Ambiguous + { + boost::unordered_map m({std::pair(1,2)}, 0, + std::hash()); + static_assert(std::is_same>>::value); + } + + { + boost::unordered_map m({std::pair(1,2)}, 0, + std::hash(), std::equal_to()); + static_assert(std::is_same, std::equal_to>>::value); + } + */ + + { + boost::unordered_map m( + {std::pair(1, 2)}, 0, f, f, pair_allocator); + static_assert(std::is_same > > >::value); + } + + /* + template + unordered_map(InputIterator, InputIterator, typename see below::size_type, + Allocator) + -> unordered_map, iter_val_t, + hash>, + equal_to>, + Allocator>; + */ + + /* Ambiguous + { + boost::unordered_map m(x.begin(), x.end(), 0u, pair_allocator); + static_assert(std::is_same, std::equal_to, test_allocator>>>::value); + } + */ + + /* + template + unordered_map(InputIterator, InputIterator, Allocator) + -> unordered_map, iter_val_t, + hash>, + equal_to>, + Allocator>; + */ + + /* No constructor: + { + boost::unordered_map m(x.begin(), x.end(), pair_allocator); + static_assert(std::is_same, std::equal_to, test_allocator>>>::value); + } + */ + + /* + template + unordered_map(InputIterator, InputIterator, typename see below::size_type, + Hash, Allocator) + -> unordered_map, iter_val_t, + Hash, + equal_to>, Allocator>; + */ + + /* Ambiguous + { + boost::unordered_map m(x.begin(), x.end(), 0u, f, pair_allocator); + static_assert(std::is_same, test_allocator>>>::value); + } + */ + + /* + template + unordered_map(initializer_list>, typename see + below::size_type, + Allocator) + -> unordered_map, equal_to, Allocator>; + */ + + /* Ambiguous + { + boost::unordered_map m({std::pair(1,2)}, 0, pair_allocator); + static_assert(std::is_same, std::equal_to, test_allocator>>>::value); + } + */ + + /* + template + unordered_map(initializer_list>, Allocator) + -> unordered_map, equal_to, Allocator>; + */ + + { + boost::unordered_map m({std::pair(1, 2)}, pair_allocator); + static_assert(std::is_same, std::equal_to, + test_allocator > > >::value); + } + + /* + template + unordered_map(initializer_list>, typename see + below::size_type, Hash, + Allocator) + -> unordered_map, Allocator>; + */ + + /* Ambiguous + { + boost::unordered_map m({std::pair(1,2)}, 0, f, + pair_allocator); + static_assert(std::is_same, std::equal_to, test_allocator>>>::value); + } + */ + + // unordered_multimap + + { + boost::unordered_multimap m(x.begin(), x.end()); + static_assert( + std::is_same >::value); + } + + /* Ambiguous: + { + boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash()); + static_assert(std::is_same>>::value); + } + + { + boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash(), + std::equal_to()); + static_assert(std::is_same, std::equal_to>>::value); + } + */ + + { + boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash(), + std::equal_to(), pair_allocator); + static_assert(std::is_same, std::equal_to, + test_allocator > > >::value); + } + + { + boost::unordered_multimap m({std::pair(1, 2)}); + static_assert( + std::is_same >::value); + } + + /* Ambiguous + { + boost::unordered_multimap m({std::pair(1,2)}, 0, + std::hash()); + static_assert(std::is_same>>::value); + } + + { + boost::unordered_multimap m({std::pair(1,2)}, 0, + std::hash(), std::equal_to()); + static_assert(std::is_same, std::equal_to>>::value); + } + */ + + { + boost::unordered_multimap m( + {std::pair(1, 2)}, 0, f, f, pair_allocator); + static_assert(std::is_same > > >::value); + } + + /* Ambiguous + { + boost::unordered_multimap m(x.begin(), x.end(), 0u, pair_allocator); + static_assert(std::is_same, std::equal_to, test_allocator>>>::value); + } + */ + + /* No constructor: + { + boost::unordered_multimap m(x.begin(), x.end(), pair_allocator); + static_assert(std::is_same, std::equal_to, test_allocator>>>::value); + } + */ + + /* Ambiguous + { + boost::unordered_multimap m(x.begin(), x.end(), 0u, f, pair_allocator); + static_assert(std::is_same, test_allocator>>>::value); + } + + { + boost::unordered_multimap m({std::pair(1,2)}, 0, + pair_allocator); + static_assert(std::is_same, std::equal_to, test_allocator>>>::value); + } + */ + + { + boost::unordered_multimap m( + {std::pair(1, 2)}, pair_allocator); + static_assert(std::is_same, std::equal_to, + test_allocator > > >::value); + } + +/* Ambiguous +{ + boost::unordered_multimap m({std::pair(1,2)}, 0, f, +pair_allocator); + static_assert(std::is_same, std::equal_to, test_allocator>>>::value); +} +*/ + +#endif +} From 15befe998ecf09f2b406e4580d31c81c15e0ea29 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 22 Dec 2017 16:44:43 +0000 Subject: [PATCH 09/50] Rename table::get_bucket to get_bucket_pointer All the other '*_bucket' methods return a bucket index. --- .../boost/unordered/detail/implementation.hpp | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index c5d143ea..a6e1fd31 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -2960,7 +2960,7 @@ namespace boost { bucket_allocator_traits::max_size(bucket_alloc()) - 1); } - bucket_pointer get_bucket(std::size_t bucket_index) const + bucket_pointer get_bucket_pointer(std::size_t bucket_index) const { BOOST_ASSERT(buckets_); return buckets_ + static_cast(bucket_index); @@ -2968,12 +2968,12 @@ namespace boost { link_pointer get_previous_start() const { - return get_bucket(bucket_count_)->first_from_start(); + return get_bucket_pointer(bucket_count_)->first_from_start(); } link_pointer get_previous_start(std::size_t bucket_index) const { - return get_bucket(bucket_index)->next_; + return get_bucket_pointer(bucket_index)->next_; } node_pointer begin() const @@ -3102,7 +3102,7 @@ namespace boost { // Clear the bucket pointers. void clear_buckets() { - bucket_pointer end = get_bucket(bucket_count_); + bucket_pointer end = get_bucket_pointer(bucket_count_); for (bucket_pointer it = buckets_; it != end; ++it) { it->next_ = node_pointer(); } @@ -3218,7 +3218,7 @@ namespace boost { for (node_pointer n = src.begin(); n; n = next_node(n)) { std::size_t bucket = n->get_bucket(); if (bucket != last_bucket) { - this->get_bucket(bucket)->next_ = prev; + this->get_bucket_pointer(bucket)->next_ = prev; } node_pointer n2 = boost::unordered::detail::func::construct_node( this->node_alloc(), boost::move(n->value())); @@ -3248,7 +3248,7 @@ namespace boost { { if (buckets_) { node_pointer n = - static_cast(get_bucket(bucket_count_)->next_); + static_cast(get_bucket_pointer(bucket_count_)->next_); if (bucket::extra_node) { node_pointer next = next_node(n); @@ -3272,7 +3272,7 @@ namespace boost { void destroy_buckets() { - bucket_pointer end = get_bucket(bucket_count_ + 1); + bucket_pointer end = get_bucket_pointer(bucket_count_ + 1); for (bucket_pointer it = buckets_; it != end; ++it) { boost::unordered::detail::func::destroy(pointer::get(it)); } @@ -3302,11 +3302,11 @@ namespace boost { } // Update the bucket containing next. - get_bucket(bucket_index2)->next_ = prev; + get_bucket_pointer(bucket_index2)->next_ = prev; } // Check if this bucket is now empty. - bucket_pointer this_bucket = get_bucket(bucket_index); + bucket_pointer this_bucket = get_bucket_pointer(bucket_index); if (this_bucket->next_ == prev) { this_bucket->next_ = link_pointer(); } @@ -3556,7 +3556,7 @@ namespace boost { node_pointer n, std::size_t key_hash) { std::size_t bucket_index = this->hash_to_bucket(key_hash); - bucket_pointer b = this->get_bucket(bucket_index); + bucket_pointer b = this->get_bucket_pointer(bucket_index); n->bucket_info_ = bucket_index; n->set_first_in_group(); @@ -3565,7 +3565,7 @@ namespace boost { link_pointer start_node = this->get_previous_start(); if (start_node->next_) { - this->get_bucket(node_bucket(next_node(start_node)))->next_ = n; + this->get_bucket_pointer(node_bucket(next_node(start_node)))->next_ = n; } b->next_ = start_node; @@ -4077,18 +4077,18 @@ namespace boost { if (n->next_) { std::size_t next_bucket = this->node_bucket(next_node(n)); if (next_bucket != bucket_index) { - this->get_bucket(next_bucket)->next_ = n; + this->get_bucket_pointer(next_bucket)->next_ = n; } } } else { n->set_first_in_group(); - bucket_pointer b = this->get_bucket(bucket_index); + bucket_pointer b = this->get_bucket_pointer(bucket_index); if (!b->next_) { link_pointer start_node = this->get_previous_start(); if (start_node->next_) { - this->get_bucket(this->node_bucket(next_node(start_node))) + this->get_bucket_pointer(this->node_bucket(next_node(start_node))) ->next_ = n; } @@ -4114,7 +4114,7 @@ namespace boost { if (n->next_) { std::size_t next_bucket = this->node_bucket(next_node(n)); if (next_bucket != this->node_bucket(n)) { - this->get_bucket(next_bucket)->next_ = n; + this->get_bucket_pointer(next_bucket)->next_ = n; } } ++this->size_; @@ -4383,7 +4383,7 @@ namespace boost { template inline void table::clear_impl() { if (size_) { - bucket_pointer end = get_bucket(bucket_count_); + bucket_pointer end = get_bucket_pointer(bucket_count_); for (bucket_pointer it = buckets_; it != end; ++it) { it->next_ = node_pointer(); } @@ -4471,7 +4471,7 @@ namespace boost { } // n is now the last node in the group - bucket_pointer b = this->get_bucket(bucket_index); + bucket_pointer b = this->get_bucket_pointer(bucket_index); if (!b->next_) { b->next_ = prev; prev = n; From 92ce66be64fb83a04d7a6f3c9b8a7f110f333805 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 22 Dec 2017 16:54:05 +0000 Subject: [PATCH 10/50] Rename 'bucket' variable to avoid shadow warning --- include/boost/unordered/detail/implementation.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index a6e1fd31..1a563131 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -3216,9 +3216,9 @@ namespace boost { link_pointer prev = this->get_previous_start(); std::size_t last_bucket = this->bucket_count_; for (node_pointer n = src.begin(); n; n = next_node(n)) { - std::size_t bucket = n->get_bucket(); - if (bucket != last_bucket) { - this->get_bucket_pointer(bucket)->next_ = prev; + std::size_t n_bucket = n->get_bucket(); + if (n_bucket != last_bucket) { + this->get_bucket_pointer(n_bucket)->next_ = prev; } node_pointer n2 = boost::unordered::detail::func::construct_node( this->node_alloc(), boost::move(n->value())); @@ -3226,7 +3226,7 @@ namespace boost { prev->next_ = n2; ++size_; prev = n2; - last_bucket = bucket; + last_bucket = n_bucket; } } } From 07758b7af8b41422168387bc59d31ac0cdd095ac Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 22 Dec 2017 16:58:15 +0000 Subject: [PATCH 11/50] Catch exceptions by reference --- test/exception/swap_exception_tests.cpp | 2 +- test/unordered/at_tests.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/exception/swap_exception_tests.cpp b/test/exception/swap_exception_tests.cpp index 242410d7..b2bec836 100644 --- a/test/exception/swap_exception_tests.cpp +++ b/test/exception/swap_exception_tests.cpp @@ -90,7 +90,7 @@ template struct swap_base : public test::exception_base { try { d.x.swap(d.y); - } catch (std::runtime_error) { + } catch (std::runtime_error&) { } DISABLE_EXCEPTIONS; diff --git a/test/unordered/at_tests.cpp b/test/unordered/at_tests.cpp index 4d91975c..25b0951a 100644 --- a/test/unordered/at_tests.cpp +++ b/test/unordered/at_tests.cpp @@ -25,13 +25,13 @@ namespace at_tests { try { x.at("one"); BOOST_ERROR("Should have thrown."); - } catch (std::out_of_range) { + } catch (std::out_of_range&) { } try { x_const.at("one"); BOOST_ERROR("Should have thrown."); - } catch (std::out_of_range) { + } catch (std::out_of_range&) { } BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl; @@ -51,13 +51,13 @@ namespace at_tests { try { x.at("three"); BOOST_ERROR("Should have thrown."); - } catch (std::out_of_range) { + } catch (std::out_of_range&) { } try { x_const.at("three"); BOOST_ERROR("Should have thrown."); - } catch (std::out_of_range) { + } catch (std::out_of_range&) { } BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl; From 64441d2b645e043fec8bb69fa7d6df67b08d4a30 Mon Sep 17 00:00:00 2001 From: Daniela Engert Date: Thu, 28 Dec 2017 12:00:59 +0100 Subject: [PATCH 12/50] Inheriting std::iterator is deprecated in c++17. Therefore get rid of all of that and replace inheritance by lifting std::iterator's members into the derived class. Signed-off-by: Daniela Engert --- .../boost/unordered/detail/implementation.hpp | 28 +++++++++++-------- test/helpers/input_iterator.hpp | 21 +++++++------- test/helpers/list.hpp | 16 +++++++++-- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 1a563131..f29e5155 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -2099,9 +2099,6 @@ namespace boost { template struct l_iterator - : public std::iterator { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template @@ -2116,6 +2113,10 @@ namespace boost { public: typedef typename Node::value_type value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; l_iterator() BOOST_NOEXCEPT : ptr_() {} @@ -2158,9 +2159,6 @@ namespace boost { template struct cl_iterator - : public std::iterator { friend struct boost::unordered::iterator_detail::l_iterator; @@ -2172,6 +2170,10 @@ namespace boost { public: typedef typename Node::value_type value_type; + typedef value_type const* pointer; + typedef value_type const& reference; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; cl_iterator() BOOST_NOEXCEPT : ptr_() {} @@ -2224,9 +2226,6 @@ namespace boost { template struct iterator - : public std::iterator { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template @@ -2240,6 +2239,10 @@ namespace boost { public: typedef typename Node::value_type value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; iterator() BOOST_NOEXCEPT : node_() {} @@ -2278,9 +2281,6 @@ namespace boost { template struct c_iterator - : public std::iterator { friend struct boost::unordered::iterator_detail::iterator; @@ -2295,6 +2295,10 @@ namespace boost { public: typedef typename Node::value_type value_type; + typedef value_type const* pointer; + typedef value_type const& reference; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; c_iterator() BOOST_NOEXCEPT : node_() {} diff --git a/test/helpers/input_iterator.hpp b/test/helpers/input_iterator.hpp index b32dbb37..6cf7c175 100644 --- a/test/helpers/input_iterator.hpp +++ b/test/helpers/input_iterator.hpp @@ -26,14 +26,14 @@ namespace test { template struct input_iterator_adaptor - : public std::iterator::value_type, - std::ptrdiff_t, - BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer, - proxy > { typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer + pointer; + typedef proxy 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) {} @@ -67,17 +67,16 @@ namespace test { template struct copy_iterator_adaptor - : public std::iterator::iterator_category, - BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type, - BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type, - BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer, - proxy > { typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type value_type; typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type difference_type; + typedef BOOST_DEDUCED_TYPENAME + std::iterator_traits::iterator_category iterator_category; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer + pointer; + typedef proxy reference; copy_iterator_adaptor() : base_() {} explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {} diff --git a/test/helpers/list.hpp b/test/helpers/list.hpp index 137cb17c..3c94e279 100644 --- a/test/helpers/list.hpp +++ b/test/helpers/list.hpp @@ -83,7 +83,6 @@ namespace test { template class list_iterator - : public std::iterator { friend class list_const_iterator; friend class test::list; @@ -93,6 +92,12 @@ namespace test { 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) {} @@ -114,8 +119,7 @@ namespace test { }; template - class list_const_iterator : public std::iterator + class list_const_iterator { friend class list_iterator; friend class test::list; @@ -126,6 +130,12 @@ namespace test { 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 const& x) : ptr_(x.ptr_) {} From 9d558b010d4029a2e4da1d9754c5c9a908db97b7 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 28 Dec 2017 11:44:57 +0000 Subject: [PATCH 13/50] Reformat --- .../boost/unordered/detail/implementation.hpp | 22 +++++++++---------- test/helpers/input_iterator.hpp | 6 ++--- test/helpers/list.hpp | 6 ++--- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index f29e5155..4be0249b 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -2097,8 +2097,7 @@ namespace boost { // // all no throw - template - struct l_iterator + template struct l_iterator { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template @@ -2157,8 +2156,7 @@ namespace boost { } }; - template - struct cl_iterator + template struct cl_iterator { friend struct boost::unordered::iterator_detail::l_iterator; @@ -2224,8 +2222,7 @@ namespace boost { } }; - template - struct iterator + template struct iterator { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template @@ -2279,8 +2276,7 @@ namespace boost { } }; - template - struct c_iterator + template struct c_iterator { friend struct boost::unordered::iterator_detail::iterator; @@ -3251,8 +3247,8 @@ namespace boost { void delete_buckets() { if (buckets_) { - node_pointer n = - static_cast(get_bucket_pointer(bucket_count_)->next_); + node_pointer n = static_cast( + get_bucket_pointer(bucket_count_)->next_); if (bucket::extra_node) { node_pointer next = next_node(n); @@ -3569,7 +3565,8 @@ namespace boost { link_pointer start_node = this->get_previous_start(); if (start_node->next_) { - this->get_bucket_pointer(node_bucket(next_node(start_node)))->next_ = n; + this->get_bucket_pointer(node_bucket(next_node(start_node))) + ->next_ = n; } b->next_ = start_node; @@ -4092,7 +4089,8 @@ namespace boost { link_pointer start_node = this->get_previous_start(); if (start_node->next_) { - this->get_bucket_pointer(this->node_bucket(next_node(start_node))) + this + ->get_bucket_pointer(this->node_bucket(next_node(start_node))) ->next_ = n; } diff --git a/test/helpers/input_iterator.hpp b/test/helpers/input_iterator.hpp index 6cf7c175..ab1a818b 100644 --- a/test/helpers/input_iterator.hpp +++ b/test/helpers/input_iterator.hpp @@ -24,8 +24,7 @@ namespace test { proxy& operator=(proxy const&); }; - template - struct input_iterator_adaptor + template struct input_iterator_adaptor { typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type value_type; @@ -65,8 +64,7 @@ namespace test { return input_iterator_adaptor(it); } - template - struct copy_iterator_adaptor + template struct copy_iterator_adaptor { typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type value_type; diff --git a/test/helpers/list.hpp b/test/helpers/list.hpp index 3c94e279..d39c766e 100644 --- a/test/helpers/list.hpp +++ b/test/helpers/list.hpp @@ -81,8 +81,7 @@ namespace test { list_data& operator=(list_data const&); }; - template - class list_iterator + template class list_iterator { friend class list_const_iterator; friend class test::list; @@ -118,8 +117,7 @@ namespace test { bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; } }; - template - class list_const_iterator + template class list_const_iterator { friend class list_iterator; friend class test::list; From be0acc575f26fbff1e447f4eac5dc2c7cb013bf8 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 3 Jan 2018 20:55:40 +0000 Subject: [PATCH 14/50] Implement allocator_traits::is_always_equal --- .../boost/unordered/detail/implementation.hpp | 153 ++++++++++-------- test/unordered/allocator_traits.cpp | 8 + 2 files changed, 95 insertions(+), 66 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 4be0249b..4272b17c 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -864,6 +864,78 @@ namespace boost { #endif +//////////////////////////////////////////////////////////////////////////// +// TRAITS TYPE DEDETION MECHANISM +// +// Used to implement traits that use a type if present, or a +// default otherwise. + +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400 + +#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \ + template struct default_type_##tname \ + { \ + \ + template \ + static choice1::type test(choice1, typename X::tname* = 0); \ + \ + template static choice2::type test(choice2, void* = 0); \ + \ + struct DefaultWrap \ + { \ + typedef Default tname; \ + }; \ + \ + enum \ + { \ + value = (1 == sizeof(test(choose()))) \ + }; \ + \ + typedef typename boost::detail::if_true::BOOST_NESTED_TEMPLATE \ + then::type::tname type; \ + } + +#else + +namespace boost { + namespace unordered { + namespace detail { + template struct sfinae : T2 + { + }; + } + } +} + +#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \ + template struct default_type_##tname \ + { \ + \ + template \ + static typename boost::unordered::detail::sfinae::type test(choice1); \ + \ + template static choice2::type test(choice2); \ + \ + struct DefaultWrap \ + { \ + typedef Default tname; \ + }; \ + \ + enum \ + { \ + value = (1 == sizeof(test(choose()))) \ + }; \ + \ + typedef typename boost::detail::if_true::BOOST_NESTED_TEMPLATE \ + then::type::tname type; \ + } + +#endif + +#define BOOST_UNORDERED_DEFAULT_TYPE(T, tname, arg) \ + typename default_type_##tname::type + //////////////////////////////////////////////////////////////////////////////// // // Allocator traits @@ -943,72 +1015,6 @@ namespace boost { } } -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400 - -#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \ - template struct default_type_##tname \ - { \ - \ - template \ - static choice1::type test(choice1, typename X::tname* = 0); \ - \ - template static choice2::type test(choice2, void* = 0); \ - \ - struct DefaultWrap \ - { \ - typedef Default tname; \ - }; \ - \ - enum \ - { \ - value = (1 == sizeof(test(choose()))) \ - }; \ - \ - typedef typename boost::detail::if_true::BOOST_NESTED_TEMPLATE \ - then::type::tname type; \ - } - -#else - -namespace boost { - namespace unordered { - namespace detail { - template struct sfinae : T2 - { - }; - } - } -} - -#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \ - template struct default_type_##tname \ - { \ - \ - template \ - static typename boost::unordered::detail::sfinae::type test(choice1); \ - \ - template static choice2::type test(choice2); \ - \ - struct DefaultWrap \ - { \ - typedef Default tname; \ - }; \ - \ - enum \ - { \ - value = (1 == sizeof(test(choose()))) \ - }; \ - \ - typedef typename boost::detail::if_true::BOOST_NESTED_TEMPLATE \ - then::type::tname type; \ - } - -#endif - -#define BOOST_UNORDERED_DEFAULT_TYPE(T, tname, arg) \ - typename default_type_##tname::type - namespace boost { namespace unordered { namespace detail { @@ -1023,6 +1029,7 @@ namespace boost { BOOST_UNORDERED_DEFAULT_TYPE_TMPLT( propagate_on_container_move_assignment); BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap); + BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(is_always_equal); #if !defined(BOOST_NO_SFINAE_EXPR) @@ -1319,6 +1326,9 @@ namespace boost { false_type) propagate_on_container_move_assignment; typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, propagate_on_container_swap, false_type) propagate_on_container_swap; + + typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, is_always_equal, + typename boost::is_empty::type) is_always_equal; }; } } @@ -1339,9 +1349,20 @@ namespace boost { namespace unordered { namespace detail { + BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(is_always_equal); + template struct allocator_traits : std::allocator_traits { + // As is_always_equal was introduced in C++17, std::allocator_traits + // doesn't always have it. So use it when available, implement it + // ourselves when not. Would be simpler not to bother with + // std::allocator_traits, but I feel like I should try to use + // it where possible. + typedef BOOST_UNORDERED_DEFAULT_TYPE(std::allocator_traits, + is_always_equal, + BOOST_UNORDERED_DEFAULT_TYPE(Alloc, is_always_equal, + typename boost::is_empty::type)) is_always_equal; }; template struct rebind_wrap diff --git a/test/unordered/allocator_traits.cpp b/test/unordered/allocator_traits.cpp index f59fc876..c6b06f85 100644 --- a/test/unordered/allocator_traits.cpp +++ b/test/unordered/allocator_traits.cpp @@ -126,6 +126,7 @@ void test_empty_allocator() 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() == 0); } @@ -139,6 +140,7 @@ template struct 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 select_on_container_copy_construction() const { @@ -166,6 +168,7 @@ void test_allocator1() 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() == 1); } @@ -192,6 +195,7 @@ template struct allocator2 : allocator2_base > 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() @@ -208,6 +212,7 @@ void test_allocator2() 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() == 1); } @@ -240,6 +245,8 @@ template struct allocator3 typedef ptr 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; @@ -267,6 +274,7 @@ void test_allocator3() 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() == 1); } From 7615fabc803499a808b97970345590de960a38dd Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 3 Jan 2018 20:55:44 +0000 Subject: [PATCH 15/50] Rewrite node handles using a lightweight limited optional Will try to use std::optional when available. Also using allocator_traits::is_always_equal support. --- .../boost/unordered/detail/implementation.hpp | 137 ++++++++++++++---- include/boost/unordered/unordered_map.hpp | 88 +++-------- include/boost/unordered/unordered_set.hpp | 82 +++-------- 3 files changed, 159 insertions(+), 148 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 4272b17c..1b9dee56 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -750,6 +750,118 @@ namespace boost { #if defined(BOOST_MSVC) #pragma warning(pop) #endif + + ////////////////////////////////////////////////////////////////////////// + // value_base + // + // Space used to store values. + + template struct value_base + { + typedef ValueType value_type; + + typename boost::aligned_storage::value>::type data_; + + value_base() : data_() {} + + void* address() { return this; } + + value_type& value() { return *(ValueType*)this; } + + value_type const& value() const { return *(ValueType const*)this; } + + value_type* value_ptr() { return (ValueType*)this; } + + value_type const* value_ptr() const { return (ValueType const*)this; } + + private: + value_base& operator=(value_base const&); + }; + + ////////////////////////////////////////////////////////////////////////// + // optional + // TODO: Use std::optional when available. + + template class optional + { + BOOST_MOVABLE_BUT_NOT_COPYABLE(optional) + + boost::unordered::detail::value_base value_; + bool has_value_; + + void destroy() + { + if (has_value_) { + boost::unordered::detail::func::destroy(value_.value_ptr()); + has_value_ = false; + } + } + + void move(optional& x) + { + BOOST_ASSERT(!has_value_ && x.has_value_); + new (value_.value_ptr()) T(boost::move(x.value_.value())); + boost::unordered::detail::func::destroy(x.value_.value_ptr()); + has_value_ = true; + x.has_value_ = false; + } + + public: + optional() BOOST_NOEXCEPT : has_value_(false) {} + + optional(BOOST_RV_REF(optional) x) : has_value_(false) + { + if (x.has_value_) { + move(x); + } + } + + explicit optional(T const& x) : has_value_(true) + { + new (value_.value_ptr()) T(x); + } + + optional& operator=(BOOST_RV_REF(optional) x) + { + destroy(); + if (x.has_value_) { + move(x); + } + return *this; + } + + ~optional() { destroy(); } + + bool has_value() const { return has_value_; } + T& operator*() { return value_.value(); } + T const& operator*() const { return value_.value(); } + T* operator->() { return value_.value_ptr(); } + T const* operator->() const { return value_.value_ptr(); } + + bool operator==(optional const& x) + { + return has_value_ ? x.has_value_ && value_.value() == x.value_.value() + : !x.has_value_; + } + + bool operator!=(optional const& x) { return !((*this) == x); } + + void swap(optional& x) + { + if (has_value_ != x.has_value_) { + if (has_value_) { + x.move(*this); + } else { + move(x); + } + } else if (has_value_) { + boost::swap(value_.value(), x.value_.value()); + } + } + + friend void swap(optional& x, optional& y) { x.swap(y); } + }; } } } @@ -2831,31 +2943,6 @@ namespace boost { : static_cast(f); } - // The space used to store values in a node. - - template struct value_base - { - typedef ValueType value_type; - - typename boost::aligned_storage::value>::type data_; - - value_base() : data_() {} - - void* address() { return this; } - - value_type& value() { return *(ValueType*)this; } - - value_type const& value() const { return *(ValueType const*)this; } - - value_type* value_ptr() { return (ValueType*)this; } - - value_type const* value_ptr() const { return (ValueType const*)this; } - - private: - value_base& operator=(value_base const&); - }; - template struct table : boost::unordered::detail::functions diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index e32f6123..06f2bb1a 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -2456,72 +2456,51 @@ namespace boost { private: node_pointer ptr_; - bool has_alloc_; - boost::unordered::detail::value_base alloc_; + boost::unordered::detail::optional alloc_; node_handle_map(node_pointer ptr, allocator_type const& a) - : ptr_(ptr), has_alloc_(false) + : ptr_(ptr), alloc_(a) { - if (ptr_) { - new ((void*)&alloc_) value_allocator(a); - has_alloc_ = true; - } } public: - BOOST_CONSTEXPR node_handle_map() BOOST_NOEXCEPT : ptr_(), - has_alloc_(false) - { - } + BOOST_CONSTEXPR node_handle_map() BOOST_NOEXCEPT : ptr_(), alloc_() {} ~node_handle_map() { - if (has_alloc_ && ptr_) { - node_allocator node_alloc(alloc_.value()); + if (ptr_) { + node_allocator node_alloc(*alloc_); boost::unordered::detail::node_tmp tmp( ptr_, node_alloc); } - if (has_alloc_) { - alloc_.value_ptr()->~value_allocator(); - } } node_handle_map(BOOST_RV_REF(node_handle_map) n) BOOST_NOEXCEPT : ptr_(n.ptr_), - has_alloc_(false) + alloc_(boost::move(n.alloc_)) { - if (n.has_alloc_) { - new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value())); - has_alloc_ = true; - n.ptr_ = node_pointer(); - n.alloc_.value_ptr()->~value_allocator(); - n.has_alloc_ = false; - } + n.ptr_ = node_pointer(); } node_handle_map& operator=(BOOST_RV_REF(node_handle_map) n) { - BOOST_ASSERT(!has_alloc_ || + BOOST_ASSERT(!alloc_.has_value() || value_allocator_traits:: propagate_on_container_move_assignment::value || - (n.has_alloc_ && alloc_.value() == n.alloc_.value())); + (n.alloc_.has_value() && alloc_ == n.alloc_)); if (ptr_) { - node_allocator node_alloc(alloc_.value()); + node_allocator node_alloc(*alloc_); boost::unordered::detail::node_tmp tmp( ptr_, node_alloc); ptr_ = node_pointer(); } - if (has_alloc_) { - alloc_.value_ptr()->~value_allocator(); - has_alloc_ = false; + if (!alloc_.has_value() || + value_allocator_traits::propagate_on_container_move_assignment:: + value) { + alloc_ = boost::move(n.alloc_); } - - if (!has_alloc_ && n.has_alloc_) { - move_allocator(n); - } - ptr_ = n.ptr_; n.ptr_ = node_pointer(); @@ -2535,7 +2514,7 @@ namespace boost { mapped_type& mapped() const { return ptr_->value().second; } - allocator_type get_allocator() const { return alloc_.value(); } + allocator_type get_allocator() const { return *alloc_; } BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() @@ -2544,38 +2523,19 @@ namespace boost { bool empty() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; } void swap(node_handle_map& n) BOOST_NOEXCEPT_IF( - value_allocator_traits::propagate_on_container_swap::value - /* || value_allocator_traits::is_always_equal::value */) + value_allocator_traits::propagate_on_container_swap::value || + value_allocator_traits::is_always_equal::value) { - if (!has_alloc_) { - if (n.has_alloc_) { - move_allocator(n); - } - } else if (!n.has_alloc_) { - n.move_allocator(*this); - } else { - swap_impl( - n, boost::unordered::detail::integral_constant()); + BOOST_ASSERT( + !alloc_.has_value() || !n.alloc_.has_value() || + value_allocator_traits::propagate_on_container_swap::value || + alloc_ == n.alloc_); + if (value_allocator_traits::propagate_on_container_swap::value || + !alloc_.has_value() || !n.alloc_.has_value()) { + boost::swap(alloc_, n.alloc_); } boost::swap(ptr_, n.ptr_); } - - private: - void move_allocator(node_handle_map& n) - { - new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value())); - n.alloc_.value_ptr()->~value_allocator(); - has_alloc_ = true; - n.has_alloc_ = false; - } - - void swap_impl(node_handle_map&, boost::unordered::detail::false_type) {} - - void swap_impl(node_handle_map& n, boost::unordered::detail::true_type) - { - boost::swap(alloc_, n.alloc_); - } }; template diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index bbd243d0..8f991660 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -1970,15 +1970,11 @@ namespace boost { private: node_pointer ptr_; bool has_alloc_; - boost::unordered::detail::value_base alloc_; + boost::unordered::detail::optional alloc_; node_handle_set(node_pointer ptr, allocator_type const& a) - : ptr_(ptr), has_alloc_(false) + : ptr_(ptr), alloc_(a) { - if (ptr_) { - new ((void*)&alloc_) value_allocator(a); - has_alloc_ = true; - } } public: @@ -1989,52 +1985,39 @@ namespace boost { ~node_handle_set() { - if (has_alloc_ && ptr_) { - node_allocator node_alloc(alloc_.value()); + if (ptr_) { + node_allocator node_alloc(*alloc_); boost::unordered::detail::node_tmp tmp( ptr_, node_alloc); } - if (has_alloc_) { - alloc_.value_ptr()->~value_allocator(); - } } node_handle_set(BOOST_RV_REF(node_handle_set) n) BOOST_NOEXCEPT : ptr_(n.ptr_), - has_alloc_(false) + alloc_(boost::move(n.alloc_)) { - if (n.has_alloc_) { - new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value())); - has_alloc_ = true; - n.ptr_ = node_pointer(); - n.alloc_.value_ptr()->~value_allocator(); - n.has_alloc_ = false; - } + n.ptr_ = node_pointer(); } node_handle_set& operator=(BOOST_RV_REF(node_handle_set) n) { - BOOST_ASSERT(!has_alloc_ || + BOOST_ASSERT(!alloc_.has_value() || value_allocator_traits:: propagate_on_container_move_assignment::value || - (n.has_alloc_ && alloc_.value() == n.alloc_.value())); + (n.alloc_.has_value() && alloc_ == n.alloc_)); if (ptr_) { - node_allocator node_alloc(alloc_.value()); + node_allocator node_alloc(*alloc_); boost::unordered::detail::node_tmp tmp( ptr_, node_alloc); ptr_ = node_pointer(); } - if (has_alloc_) { - alloc_.value_ptr()->~value_allocator(); - has_alloc_ = false; + if (!alloc_.has_value() || + value_allocator_traits::propagate_on_container_move_assignment:: + value) { + alloc_ = boost::move(n.alloc_); } - - if (!has_alloc_ && n.has_alloc_) { - move_allocator(n); - } - ptr_ = n.ptr_; n.ptr_ = node_pointer(); @@ -2043,7 +2026,7 @@ namespace boost { value_type& value() const { return ptr_->value(); } - allocator_type get_allocator() const { return alloc_.value(); } + allocator_type get_allocator() const { return *alloc_; } BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() @@ -2052,38 +2035,19 @@ namespace boost { bool empty() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; } void swap(node_handle_set& n) BOOST_NOEXCEPT_IF( - value_allocator_traits::propagate_on_container_swap::value - /* || value_allocator_traits::is_always_equal::value */) + value_allocator_traits::propagate_on_container_swap::value || + value_allocator_traits::is_always_equal::value) { - if (!has_alloc_) { - if (n.has_alloc_) { - move_allocator(n); - } - } else if (!n.has_alloc_) { - n.move_allocator(*this); - } else { - swap_impl( - n, boost::unordered::detail::integral_constant()); + BOOST_ASSERT( + !alloc_.has_value() || !n.alloc_.has_value() || + value_allocator_traits::propagate_on_container_swap::value || + alloc_ == n.alloc_); + if (value_allocator_traits::propagate_on_container_swap::value || + !alloc_.has_value() || !n.alloc_.has_value()) { + boost::swap(alloc_, n.alloc_); } boost::swap(ptr_, n.ptr_); } - - private: - void move_allocator(node_handle_set& n) - { - new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value())); - n.alloc_.value_ptr()->~value_allocator(); - has_alloc_ = true; - n.has_alloc_ = false; - } - - void swap_impl(node_handle_set&, boost::unordered::detail::false_type) {} - - void swap_impl(node_handle_set& n, boost::unordered::detail::true_type) - { - boost::swap(alloc_, n.alloc_); - } }; template From 4bffd7a85dde1486a033f7cac79065f127c5f555 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 4 Jan 2018 18:08:13 +0000 Subject: [PATCH 16/50] Avoid some warnings --- test/helpers/helpers.hpp | 3 +- test/unordered/equality_tests.cpp | 57 +++++++++++++++---------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/test/helpers/helpers.hpp b/test/helpers/helpers.hpp index e34bf259..854ebfc7 100644 --- a/test/helpers/helpers.hpp +++ b/test/helpers/helpers.hpp @@ -47,7 +47,8 @@ namespace test { template Iterator next(Iterator it, IntType x) { - std::advance(it, x); + std::advance(it, + static_cast::difference_type>(x)); return it; } } diff --git a/test/unordered/equality_tests.cpp b/test/unordered/equality_tests.cpp index 3ff61a1b..b1029af4 100644 --- a/test/unordered/equality_tests.cpp +++ b/test/unordered/equality_tests.cpp @@ -31,36 +31,36 @@ namespace equality_tests { }; #define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \ - do { \ + { \ boost::unordered_set 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); \ - } while (0) + } #define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \ - do { \ + { \ boost::unordered_multiset 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); \ - } while (0) + } #define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \ - do { \ + { \ boost::unordered_map 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); \ - } while (0) + } #define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \ - do { \ + { \ boost::unordered_multimap 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); \ - } while (0) + } #define UNORDERED_SET_INSERT(r, set, item) set.insert(item); #define UNORDERED_MAP_INSERT(r, map, item) \ @@ -89,46 +89,45 @@ namespace equality_tests { } 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_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_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_MULTISET_TEST((10)(20)(20), !=, (10)(10)(20)) UNORDERED_EQUALITY_MULTIMAP_TEST( - ((10)(1))((20)(1))((20)(1)), !=, ((10)(1))((20)(1))((10)(1))); + ((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))); + ((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_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_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)); + (3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1)) } // Test that equality still works when the two containers have From daeaf5e98b366aeefe6397ce2f6a0d2b07a37a3c Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 5 Jan 2018 17:10:13 +0000 Subject: [PATCH 17/50] Flexible exception testing hash/equal_to --- test/unordered/noexcept_tests.cpp | 80 +++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/test/unordered/noexcept_tests.cpp b/test/unordered/noexcept_tests.cpp index 98dfa2b2..29c805a2 100644 --- a/test/unordered/noexcept_tests.cpp +++ b/test/unordered/noexcept_tests.cpp @@ -42,25 +42,36 @@ namespace noexcept_tests { } } - class hash_nothrow_move : boost::hash + template + class hash_nothrow : boost::hash { - BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move) + BOOST_COPYABLE_AND_MOVABLE(hash_nothrow) typedef boost::hash base; public: - hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move)) BOOST_NOEXCEPT {} + hash_nothrow(BOOST_RV_REF(hash_nothrow)) + BOOST_NOEXCEPT_IF(nothrow_move_construct) + { + if (!nothrow_move_construct) { + test_throw("Move Constructor"); + } + } - hash_nothrow_move() { test_throw("Constructor"); } - hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); } - hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move)) + 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_move& operator=(BOOST_RV_REF(hash_nothrow_move)) + hash_nothrow& operator=(BOOST_RV_REF(hash_nothrow)) + BOOST_NOEXCEPT_IF(nothrow_move_assign) { - test_throw("Move Assign"); + if (!nothrow_move_assign) { + test_throw("Move Assign"); + } return *this; } std::size_t operator()(int x) const @@ -68,36 +79,65 @@ namespace noexcept_tests { test_throw("Operator"); return static_cast(*this)(x); } + friend void swap(hash_nothrow&, hash_nothrow&) + BOOST_NOEXCEPT_IF(nothrow_swap) + { + if (!nothrow_swap) { + test_throw("Swap"); + } + } }; - class equal_to_nothrow_move : std::equal_to - { - BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move) + typedef hash_nothrow hash_nothrow_move; - typedef std::equal_to base; + template + class equal_to_nothrow + { + BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow) + + typedef boost::hash base; public: - equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move)) BOOST_NOEXCEPT {} - equal_to_nothrow_move() { test_throw("Constructor"); } - equal_to_nothrow_move(equal_to_nothrow_move const&) { test_throw("Copy"); } - equal_to_nothrow_move& operator=( - BOOST_COPY_ASSIGN_REF(equal_to_nothrow_move)) + 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_move& operator=(BOOST_RV_REF(equal_to_nothrow_move)) + equal_to_nothrow& operator=(BOOST_RV_REF(equal_to_nothrow)) + BOOST_NOEXCEPT_IF(nothrow_move_assign) { - test_throw("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 static_cast(*this)(x, y); + 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 equal_to_nothrow_move; + bool have_is_nothrow_move = false; UNORDERED_AUTO_TEST (check_is_nothrow_move) { From 7e28fdd45a9868325b00debce145088232e1dd02 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 5 Jan 2018 17:10:13 +0000 Subject: [PATCH 18/50] Make the current function_pair public --- .../boost/unordered/detail/implementation.hpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 1b9dee56..5644773e 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -2770,18 +2770,20 @@ namespace boost { bool current_; // The currently active functions. aligned_function funcs_[2]; - function_pair const& current() const + public: + function_pair const& current_functions() const { return *static_cast( static_cast(funcs_[current_].address())); } - function_pair& current() + function_pair& current_functions() { return *static_cast( static_cast(funcs_[current_].address())); } + private: void construct(bool which, H const& hf, P const& eq) { new ((void*)&funcs_[which]) function_pair(hf, eq); @@ -2819,22 +2821,22 @@ namespace boost { functions(functions const& bf) : current_(false) { - construct(current_, bf.current()); + construct(current_, bf.current_functions()); } functions(functions& bf, boost::unordered::detail::move_tag) : current_(false) { - construct(current_, bf.current(), + construct(current_, bf.current_functions(), boost::unordered::detail::integral_constant()); } ~functions() { this->destroy(current_); } - H const& hash_function() const { return current().first(); } + H const& hash_function() const { return current_functions().first(); } - P const& key_eq() const { return current().second(); } + P const& key_eq() const { return current_functions().second(); } }; template class set_hash_functions @@ -2857,7 +2859,7 @@ namespace boost { set_hash_functions(functions_type& f, functions_type const& other) : functions_(f), tmp_functions_(!f.current_) { - f.construct(tmp_functions_, other.current()); + f.construct(tmp_functions_, other.current_functions()); } ~set_hash_functions() { functions_.destroy(tmp_functions_); } @@ -2893,8 +2895,8 @@ namespace boost { void commit() { - functions_.current().first() = boost::move(hash_); - functions_.current().second() = boost::move(pred_); + functions_.current_functions().first() = boost::move(hash_); + functions_.current_functions().second() = boost::move(pred_); } }; From 5854090dc79d73657fe2589eec73af0171c452b3 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 5 Jan 2018 17:48:13 +0000 Subject: [PATCH 19/50] Swap noexcept support Not properly supported as we don't have is_nothrow_swappable yet. --- .../boost/unordered/detail/implementation.hpp | 53 +++++++++++++++++-- include/boost/unordered/unordered_map.hpp | 32 +++++------ include/boost/unordered/unordered_set.hpp | 32 +++++------ test/unordered/noexcept_tests.cpp | 50 +++++++++++++++++ 4 files changed, 127 insertions(+), 40 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 5644773e..a44a2c27 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -31,12 +31,15 @@ #include #include #include +#include #include #include +#include #include #include #include #include +#include #include #include #include @@ -751,6 +754,19 @@ namespace boost { #pragma warning(pop) #endif + //////////////////////////////////////////////////////////////////////////// + // is_nothrow_swappable + // + // TODO: Replace this very basic implementation when the full type_traits + // implementation is available. + + template + struct is_nothrow_swappable + : boost::integral_constant::value && !boost::is_const::value> + { + }; + ////////////////////////////////////////////////////////////////////////// // value_base // @@ -2756,6 +2772,9 @@ namespace boost { static const bool nothrow_move_constructible = boost::is_nothrow_move_constructible::value && boost::is_nothrow_move_constructible

::value; + static const bool nothrow_swappable = + boost::unordered::detail::is_nothrow_swappable::value && + boost::unordered::detail::is_nothrow_swappable

::value; private: friend class boost::unordered::detail::set_hash_functions::propagate_on_container_swap::value>()); + + boost::swap(buckets_, x.buckets_); + boost::swap(bucket_count_, x.bucket_count_); + boost::swap(size_, x.size_); + std::swap(mlf_, x.mlf_); + std::swap(max_load_, x.max_load_); + this->current_functions().swap(x.current_functions()); + } + + // Only swaps the allocators if propagate_on_container_swap. + // If not propagate_on_container_swap and allocators aren't + // equal, behaviour is undefined. + void swap(table& x) + { + BOOST_ASSERT(allocator_traits< + node_allocator>::propagate_on_container_swap::value || + node_alloc() == x.node_alloc()); + swap(x, boost::unordered::detail::integral_constant()); + } + // Only call with nodes allocated with the currect allocator, or // one that is equal to it. (Can't assert because other's // allocators might have already been moved). diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 06f2bb1a..58d18944 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -715,11 +715,10 @@ namespace boost { BOOST_UNORDERED_DEPRECATED("Use erase instead") void erase_return_void(const_iterator it) { erase(it); } - void swap(unordered_map&); - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + void swap(unordered_map&) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::unordered::detail::is_nothrow_swappable::value&& + boost::unordered::detail::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -1327,11 +1326,10 @@ namespace boost { BOOST_UNORDERED_DEPRECATED("Use erase instead") void erase_return_void(const_iterator it) { erase(it); } - void swap(unordered_multimap&); - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + void swap(unordered_multimap&) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::unordered::detail::is_nothrow_swappable::value&& + boost::unordered::detail::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -1740,10 +1738,9 @@ namespace boost { template void unordered_map::swap(unordered_map& other) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::unordered::detail::is_nothrow_swappable::value&& + boost::unordered::detail::is_nothrow_swappable

::value) { table_.swap(other.table_); } @@ -2217,10 +2214,9 @@ namespace boost { template void unordered_multimap::swap(unordered_multimap& other) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::unordered::detail::is_nothrow_swappable::value&& + boost::unordered::detail::is_nothrow_swappable

::value) { table_.swap(other.table_); } diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 8f991660..e119ee76 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -441,11 +441,10 @@ namespace boost { BOOST_UNORDERED_DEPRECATED("Use erase instead") void erase_return_void(const_iterator it) { erase(it); } - void swap(unordered_set&); - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + void swap(unordered_set&) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::unordered::detail::is_nothrow_swappable::value&& + boost::unordered::detail::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -991,11 +990,10 @@ namespace boost { BOOST_UNORDERED_DEPRECATED("Use erase instead") void erase_return_void(const_iterator it) { erase(it); } - void swap(unordered_multiset&); - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + void swap(unordered_multiset&) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::unordered::detail::is_nothrow_swappable::value&& + boost::unordered::detail::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -1365,10 +1363,9 @@ namespace boost { template void unordered_set::swap(unordered_set& other) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::unordered::detail::is_nothrow_swappable::value&& + boost::unordered::detail::is_nothrow_swappable

::value) { table_.swap(other.table_); } @@ -1760,10 +1757,9 @@ namespace boost { template void unordered_multiset::swap(unordered_multiset& other) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::unordered::detail::is_nothrow_swappable::value&& + boost::unordered::detail::is_nothrow_swappable

::value) { table_.swap(other.table_); } diff --git a/test/unordered/noexcept_tests.cpp b/test/unordered/noexcept_tests.cpp index 29c805a2..f5a38a19 100644 --- a/test/unordered/noexcept_tests.cpp +++ b/test/unordered/noexcept_tests.cpp @@ -89,6 +89,7 @@ namespace noexcept_tests { }; typedef hash_nothrow hash_nothrow_move; + typedef hash_nothrow hash_nothrow_swap; template @@ -137,14 +138,18 @@ namespace noexcept_tests { }; typedef equal_to_nothrow equal_to_nothrow_move; + typedef equal_to_nothrow equal_to_nothrow_swap; bool have_is_nothrow_move = false; + bool have_is_nothrow_swap = false; UNORDERED_AUTO_TEST (check_is_nothrow_move) { BOOST_TEST( !boost::is_nothrow_move_constructible::value); have_is_nothrow_move = boost::is_nothrow_move_constructible::value; + have_is_nothrow_swap = + boost::unordered::detail::is_nothrow_swappable::value; // Copied from boost::is_nothrow_move_constructible implementation // to make sure this does actually detect it when expected. @@ -156,6 +161,17 @@ namespace noexcept_tests { !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) BOOST_TEST(have_is_nothrow_move); #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) +// TODO: Turn test on when unordered starts to use is_nothrow_swap +// 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) { @@ -203,6 +219,40 @@ namespace noexcept_tests { throwing_test_exception = false; } } + + UNORDERED_AUTO_TEST (test_nothrow_swap_when_noexcept) { + typedef boost::unordered_set + throwing_set; + + if (have_is_nothrow_swap) { + BOOST_TEST( + boost::unordered::detail::is_nothrow_swappable::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; + } } RUN_TESTS() From f12009fc61cfe5b073749cb5602afe5bbda9a468 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 5 Jan 2018 17:54:44 +0000 Subject: [PATCH 20/50] operator= noexcept support --- .../boost/unordered/detail/implementation.hpp | 85 +++++++++---- include/boost/unordered/unordered_map.hpp | 28 ++--- include/boost/unordered/unordered_set.hpp | 28 ++--- test/unordered/noexcept_tests.cpp | 113 +++++++++++++----- 4 files changed, 169 insertions(+), 85 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index a44a2c27..3e5d95f6 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -3540,49 +3540,86 @@ namespace boost { move_assign(x, is_unique, boost::unordered::detail::integral_constant:: - propagate_on_container_move_assignment::value>()); + propagate_on_container_move_assignment::value>(), + boost::unordered::detail::integral_constant()); } } + // Propagate allocator, move assign functions throwable template - void move_assign(table& x, UniqueType, true_type) + void move_assign(table& x, UniqueType, true_type, false_type) { - delete_buckets(); set_hash_functions new_func_this(*this, x); + // TODO: Can this throw? If so then breaks noexcept spec. + // Maybe don't do it if allocators are equal. + delete_buckets(); allocators_.move_assign(x.allocators_); - // No throw from here. mlf_ = x.mlf_; move_buckets_from(x); new_func_this.commit(); } + // Propagate allocator, move assign functions noexcept template - void move_assign(table& x, UniqueType is_unique, false_type) + void move_assign(table& x, UniqueType, true_type, true_type) + { + delete_buckets(); + allocators_.move_assign(x.allocators_); + mlf_ = x.mlf_; + move_buckets_from(x); + this->current_functions().move_assign(x.current_functions()); + } + + // Don't propagate allocator + template + void move_assign( + table& x, UniqueType is_unique, false_type, IsNoExcept is_noexcept) { if (node_alloc() == x.node_alloc()) { - delete_buckets(); - set_hash_functions new_func_this(*this, x); - // No throw from here. - mlf_ = x.mlf_; - move_buckets_from(x); - new_func_this.commit(); + move_assign_equal_alloc(x, is_noexcept); } else { - set_hash_functions new_func_this(*this, x); - mlf_ = x.mlf_; - recalculate_max_load(); - - if (x.size_ > max_load_) { - create_buckets(min_buckets_for_size(x.size_)); - } else if (size_) { - clear_buckets(); - } - - new_func_this.commit(); - - move_assign_buckets(x, is_unique); + move_assign_realloc(x, is_unique); } } + // Move assign functions throwable + void move_assign_equal_alloc(table& x, false_type) + { + set_hash_functions new_func_this(*this, x); + delete_buckets(); + mlf_ = x.mlf_; + move_buckets_from(x); + new_func_this.commit(); + } + + // Move assign functions noexcept + void move_assign_equal_alloc(table& x, true_type) + { + delete_buckets(); + mlf_ = x.mlf_; + move_buckets_from(x); + this->current_functions().move_assign(x.current_functions()); + } + + template + void move_assign_realloc(table& x, UniqueType is_unique) + { + set_hash_functions new_func_this(*this, x); + mlf_ = x.mlf_; + recalculate_max_load(); + + if (x.size_ > max_load_) { + create_buckets(min_buckets_for_size(x.size_)); + } else if (size_) { + clear_buckets(); + } + + new_func_this.commit(); + + move_assign_buckets(x, is_unique); + } + // Accessors const_key_type& get_key(node_pointer n) const diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 58d18944..340bb5ef 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -151,10 +151,9 @@ namespace boost { } unordered_map& operator=(BOOST_RV_REF(unordered_map) x) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::is_nothrow_move_assignable::value&& + boost::is_nothrow_move_assignable

::value) { table_.move_assign(x.table_, boost::unordered::detail::true_type()); return *this; @@ -168,10 +167,9 @@ namespace boost { #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_map& operator=(unordered_map&& x) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::is_nothrow_move_assignable::value&& + boost::is_nothrow_move_assignable

::value) { table_.move_assign(x.table_, boost::unordered::detail::true_type()); return *this; @@ -1023,10 +1021,9 @@ namespace boost { } unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::is_nothrow_move_assignable::value&& + boost::is_nothrow_move_assignable

::value) { table_.move_assign(x.table_, boost::unordered::detail::false_type()); return *this; @@ -1040,10 +1037,9 @@ namespace boost { #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_multimap& operator=(unordered_multimap&& x) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::is_nothrow_move_assignable::value&& + boost::is_nothrow_move_assignable

::value) { table_.move_assign(x.table_, boost::unordered::detail::false_type()); return *this; diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index e119ee76..f83c3526 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -149,10 +149,9 @@ namespace boost { } unordered_set& operator=(BOOST_RV_REF(unordered_set) x) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::is_nothrow_move_assignable::value&& + boost::is_nothrow_move_assignable

::value) { table_.move_assign(x.table_, boost::unordered::detail::true_type()); return *this; @@ -166,10 +165,9 @@ namespace boost { #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_set& operator=(unordered_set&& x) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::is_nothrow_move_assignable::value&& + boost::is_nothrow_move_assignable

::value) { table_.move_assign(x.table_, boost::unordered::detail::true_type()); return *this; @@ -706,10 +704,9 @@ namespace boost { } unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::is_nothrow_move_assignable::value&& + boost::is_nothrow_move_assignable

::value) { table_.move_assign(x.table_, boost::unordered::detail::false_type()); return *this; @@ -723,10 +720,9 @@ namespace boost { #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_multiset& operator=(unordered_multiset&& x) - // C++17 support: BOOST_NOEXCEPT_IF( - // value_allocator_traits::is_always_equal::value && - // is_nothrow_move_assignable_v && - // is_nothrow_move_assignable_v

) + BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& + boost::is_nothrow_move_assignable::value&& + boost::is_nothrow_move_assignable

::value) { table_.move_assign(x.table_, boost::unordered::detail::false_type()); return *this; diff --git a/test/unordered/noexcept_tests.cpp b/test/unordered/noexcept_tests.cpp index f5a38a19..84bb404e 100644 --- a/test/unordered/noexcept_tests.cpp +++ b/test/unordered/noexcept_tests.cpp @@ -18,11 +18,19 @@ namespace noexcept_tests { struct hash_possible_exception : boost::hash { 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 { 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 @@ -88,7 +96,8 @@ namespace noexcept_tests { } }; - typedef hash_nothrow hash_nothrow_move; + typedef hash_nothrow hash_nothrow_move_construct; + typedef hash_nothrow hash_nothrow_move_assign; typedef hash_nothrow hash_nothrow_swap; template equal_to_nothrow_move; + typedef equal_to_nothrow equal_to_nothrow_move_construct; + typedef equal_to_nothrow equal_to_nothrow_move_assign; typedef equal_to_nothrow 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::value); + BOOST_TEST( + !boost::is_nothrow_move_assignable::value); + BOOST_TEST(!boost::unordered::detail::is_nothrow_swappable< + hash_possible_exception>::value); + BOOST_TEST((!boost::is_nothrow_move_constructible< + equal_to_nothrow >::value)); + BOOST_TEST((!boost::is_nothrow_move_assignable< + equal_to_nothrow >::value)); + BOOST_TEST((!boost::unordered::detail::is_nothrow_swappable< + equal_to_nothrow >::value)); + have_is_nothrow_move = - boost::is_nothrow_move_constructible::value; + boost::is_nothrow_move_constructible::value; + have_is_nothrow_move_assign = + boost::is_nothrow_move_assignable::value; have_is_nothrow_swap = boost::unordered::detail::is_nothrow_swappable::value; -// Copied from boost::is_nothrow_move_constructible implementation -// to make sure this does actually detect it when expected. -// -// The type trait is also available when BOOST_IS_NOTHROW_MOVE_CONSTRUCT -// is defined (for some versions of Visual C++?) but detects 'throw()', -// not noexcept. +// 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) && \ @@ -193,31 +213,66 @@ namespace noexcept_tests { boost::hash, equal_to_possible_exception> >::value)); } - UNORDERED_AUTO_TEST (test_no_throw_when_noexcept) { - typedef boost::unordered_set + UNORDERED_AUTO_TEST (test_nothrow_move_when_noexcept) { + typedef boost::unordered_set throwing_set; if (have_is_nothrow_move) { BOOST_TEST(boost::is_nothrow_move_constructible::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); - } catch (test_exception) { - BOOST_TEST(false); - } - - throwing_test_exception = false; } + + 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 + throwing_set; + + if (have_is_nothrow_move_assign) { + BOOST_TEST(boost::is_nothrow_move_assignable::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) { From 34e54b35e8ba21b48998153e7185a820a203f6ae Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 6 Jan 2018 12:53:37 +0000 Subject: [PATCH 21/50] Manually handle assigning hash/equality functions --- .../boost/unordered/detail/implementation.hpp | 309 ++++++++---------- 1 file changed, 132 insertions(+), 177 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 3e5d95f6..c3afa7fa 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -2748,20 +2748,13 @@ namespace boost { ////////////////////////////////////////////////////////////////////////// // Functions - - // Assigning and swapping the equality and hash function objects - // needs strong exception safety. To implement that normally we'd - // require one of them to be known to not throw and the other to - // guarantee strong exception safety. Unfortunately they both only - // have basic exception safety. So to acheive strong exception - // safety we have storage space for two copies, and assign the new - // copies to the unused space. Then switch to using that to use - // them. This is implemented in 'set_hash_functions' which - // atomically assigns the new function objects in a strongly - // exception safe manner. - - template - class set_hash_functions; + // + // This double buffers the storage for the hash function and key equality + // predicate in order to have exception safe copy/swap. To do so, + // use 'construct_spare' to construct in the spare space, and then when + // ready to use 'switch_functions' to switch to the new functions. + // If an exception is thrown between these two calls, use + // 'cleanup_spare_functions' to destroy the unused constructed functions. template class functions { @@ -2777,8 +2770,6 @@ namespace boost { boost::unordered::detail::is_nothrow_swappable

::value; private: - friend class boost::unordered::detail::set_hash_functions; functions& operator=(functions const&); typedef compressed function_pair; @@ -2786,137 +2777,98 @@ namespace boost { typedef typename boost::aligned_storage::value>::type aligned_function; - bool current_; // The currently active functions. + unsigned char current_; // 0/1 - Currently active functions + // +2 - Both constructed aligned_function funcs_[2]; public: + functions(H const& hf, P const& eq) : current_(0) + { + construct_functions(current_, hf, eq); + } + + functions(functions const& bf) : current_(0) + { + construct_functions(current_, bf.current_functions()); + } + + functions(functions& bf, boost::unordered::detail::move_tag) + : current_(0) + { + construct_functions(current_, bf.current_functions(), + boost::unordered::detail::integral_constant()); + } + + ~functions() + { + BOOST_ASSERT(!(current_ & 2)); + destroy_functions(current_); + } + + H const& hash_function() const { return current_functions().first(); } + + P const& key_eq() const { return current_functions().second(); } + function_pair const& current_functions() const { return *static_cast( - static_cast(funcs_[current_].address())); + static_cast(funcs_[current_ & 1].address())); } function_pair& current_functions() { return *static_cast( - static_cast(funcs_[current_].address())); + static_cast(funcs_[current_ & 1].address())); + } + + void construct_spare_functions(function_pair const& f) + { + BOOST_ASSERT(!(current_ & 2)); + construct_functions(current_ ^ 1, f); + current_ |= 2; + } + + void cleanup_spare_functions() + { + if (current_ & 2) { + current_ &= 1; + destroy_functions(current_ ^ 1); + } + } + + void switch_functions() + { + BOOST_ASSERT(current_ & 2); + destroy_functions(current_ & 1); + current_ ^= 3; } private: - void construct(bool which, H const& hf, P const& eq) + void construct_functions(bool which, H const& hf, P const& eq) { new ((void*)&funcs_[which]) function_pair(hf, eq); } - void construct(bool which, function_pair const& f, + void construct_functions(bool which, function_pair const& f, boost::unordered::detail::false_type = boost::unordered::detail::false_type()) { new ((void*)&funcs_[which]) function_pair(f); } - void construct( + void construct_functions( bool which, function_pair& f, boost::unordered::detail::true_type) { new ((void*)&funcs_[which]) function_pair(f, boost::unordered::detail::move_tag()); } - void destroy(bool which) + void destroy_functions(bool which) { boost::unordered::detail::func::destroy( (function_pair*)(&funcs_[which])); } - - public: - typedef boost::unordered::detail::set_hash_functions - set_hash_functions; - - functions(H const& hf, P const& eq) : current_(false) - { - construct(current_, hf, eq); - } - - functions(functions const& bf) : current_(false) - { - construct(current_, bf.current_functions()); - } - - functions(functions& bf, boost::unordered::detail::move_tag) - : current_(false) - { - construct(current_, bf.current_functions(), - boost::unordered::detail::integral_constant()); - } - - ~functions() { this->destroy(current_); } - - H const& hash_function() const { return current_functions().first(); } - - P const& key_eq() const { return current_functions().second(); } - }; - - template class set_hash_functions - { - set_hash_functions(set_hash_functions const&); - set_hash_functions& operator=(set_hash_functions const&); - - typedef functions functions_type; - - functions_type& functions_; - bool tmp_functions_; - - public: - set_hash_functions(functions_type& f, H const& h, P const& p) - : functions_(f), tmp_functions_(!f.current_) - { - f.construct(tmp_functions_, h, p); - } - - set_hash_functions(functions_type& f, functions_type const& other) - : functions_(f), tmp_functions_(!f.current_) - { - f.construct(tmp_functions_, other.current_functions()); - } - - ~set_hash_functions() { functions_.destroy(tmp_functions_); } - - void commit() - { - functions_.current_ = tmp_functions_; - tmp_functions_ = !tmp_functions_; - } - }; - - template class set_hash_functions - { - set_hash_functions(set_hash_functions const&); - set_hash_functions& operator=(set_hash_functions const&); - - typedef functions functions_type; - - functions_type& functions_; - H hash_; - P pred_; - - public: - set_hash_functions(functions_type& f, H const& h, P const& p) - : functions_(f), hash_(h), pred_(p) - { - } - - set_hash_functions(functions_type& f, functions_type const& other) - : functions_(f), hash_(other.hash_function()), pred_(other.key_eq()) - { - } - - void commit() - { - functions_.current_functions().first() = boost::move(hash_); - functions_.current_functions().second() = boost::move(pred_); - } }; //////////////////////////////////////////////////////////////////////////// @@ -2991,7 +2943,6 @@ namespace boost { typedef boost::unordered::detail::functions functions; - typedef typename functions::set_hash_functions set_hash_functions; typedef typename Types::value_allocator value_allocator; typedef typename boost::unordered::detail::rebind_wrapconstruct_spare_functions(x.current_functions()); + BOOST_TRY { + x.construct_spare_functions(this->current_functions()); + } BOOST_CATCH(...) { + this->cleanup_spare_functions(); + BOOST_RETHROW + } + BOOST_CATCH_END + this->switch_functions(); + x.switch_functions(); swap_allocators( x, boost::unordered::detail::integral_constantconstruct_spare_functions(x.current_functions()); + BOOST_TRY + { + mlf_ = x.mlf_; + recalculate_max_load(); - if (x.size_ > max_load_) { - create_buckets(min_buckets_for_size(x.size_)); - } else if (size_) { - clear_buckets(); + if (x.size_ > max_load_) { + create_buckets(min_buckets_for_size(x.size_)); + } else if (size_) { + clear_buckets(); + } } - - new_func_this.commit(); - + BOOST_CATCH(...) + { + this->cleanup_spare_functions(); + BOOST_RETHROW + } + BOOST_CATCH_END + this->switch_functions(); assign_buckets(x, is_unique); } @@ -3514,7 +3480,8 @@ namespace boost { allocators_.assign(x.allocators_); assign(x, is_unique, false_type()); } else { - set_hash_functions new_func_this(*this, x); + this->construct_spare_functions(x.current_functions()); + this->switch_functions(); // Delete everything with current allocators before assigning // the new ones. @@ -3522,7 +3489,6 @@ namespace boost { allocators_.assign(x.allocators_); // Copy over other data, all no throw. - new_func_this.commit(); mlf_ = x.mlf_; bucket_count_ = min_buckets_for_size(x.size_); @@ -3540,83 +3506,72 @@ namespace boost { move_assign(x, is_unique, boost::unordered::detail::integral_constant:: - propagate_on_container_move_assignment::value>(), - boost::unordered::detail::integral_constant()); + propagate_on_container_move_assignment::value>()); } } - // Propagate allocator, move assign functions throwable + // Propagate allocator template - void move_assign(table& x, UniqueType, true_type, false_type) + void move_assign(table& x, UniqueType, true_type) { - set_hash_functions new_func_this(*this, x); - // TODO: Can this throw? If so then breaks noexcept spec. - // Maybe don't do it if allocators are equal. + if (!functions::nothrow_move_assignable) { + this->construct_spare_functions(x.current_functions()); + this->switch_functions(); + } else { + this->current_functions().move_assign(x.current_functions()); + } delete_buckets(); allocators_.move_assign(x.allocators_); mlf_ = x.mlf_; move_buckets_from(x); - new_func_this.commit(); - } - - // Propagate allocator, move assign functions noexcept - template - void move_assign(table& x, UniqueType, true_type, true_type) - { - delete_buckets(); - allocators_.move_assign(x.allocators_); - mlf_ = x.mlf_; - move_buckets_from(x); - this->current_functions().move_assign(x.current_functions()); } // Don't propagate allocator - template - void move_assign( - table& x, UniqueType is_unique, false_type, IsNoExcept is_noexcept) + template + void move_assign(table& x, UniqueType is_unique, false_type) { if (node_alloc() == x.node_alloc()) { - move_assign_equal_alloc(x, is_noexcept); + move_assign_equal_alloc(x); } else { move_assign_realloc(x, is_unique); } } - // Move assign functions throwable - void move_assign_equal_alloc(table& x, false_type) + void move_assign_equal_alloc(table& x) { - set_hash_functions new_func_this(*this, x); + if (!functions::nothrow_move_assignable) { + this->construct_spare_functions(x.current_functions()); + this->switch_functions(); + } else { + this->current_functions().move_assign(x.current_functions()); + } delete_buckets(); mlf_ = x.mlf_; move_buckets_from(x); - new_func_this.commit(); - } - - // Move assign functions noexcept - void move_assign_equal_alloc(table& x, true_type) - { - delete_buckets(); - mlf_ = x.mlf_; - move_buckets_from(x); - this->current_functions().move_assign(x.current_functions()); } template void move_assign_realloc(table& x, UniqueType is_unique) { - set_hash_functions new_func_this(*this, x); - mlf_ = x.mlf_; - recalculate_max_load(); + this->construct_spare_functions(x.current_functions()); + BOOST_TRY + { + mlf_ = x.mlf_; + recalculate_max_load(); - if (x.size_ > max_load_) { - create_buckets(min_buckets_for_size(x.size_)); - } else if (size_) { - clear_buckets(); + if (x.size_ > max_load_) { + create_buckets(min_buckets_for_size(x.size_)); + } else if (size_) { + clear_buckets(); + } } - - new_func_this.commit(); - + BOOST_CATCH(...) + { + this->cleanup_spare_functions(); + BOOST_RETHROW + } + BOOST_CATCH_END + this->switch_functions(); move_assign_buckets(x, is_unique); } From c05c541216f3823fc1a4aef74203a490b2406a7a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 6 Jan 2018 13:37:04 +0000 Subject: [PATCH 22/50] Use boost build's new cxxstd feature --- .travis.yml | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index becacec7..40561811 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,26 +19,20 @@ matrix: include: - compiler: gcc env: | - label="gcc C++03"; - user_config="using gcc : : g++-4.8 --coverage -fsanitize=address -Werror --std=c++03 ;" - enable_coverage=1 - - compiler: gcc - env: | - label="gcc C++11"; - user_config="using gcc : : g++-4.8 --coverage -fsanitize=address -Werror --std=c++11 ;" + label="gcc C++03/11"; + user_config="using gcc : : g++-4.8 --coverage -fsanitize=address -Werror ;" enable_coverage=1 + CXXSTD=03,11 - compiler: gcc env: | label="gcc 32 bit C++11"; - user_config="using gcc : : g++-4.8 -m32 -fsanitize=address -Werror --std=c++11 ;" + user_config="using gcc : : g++-4.8 -m32 -fsanitize=address -Werror ;" + CXXSTD=11 - compiler: clang env: | - label="clang C++17"; - user_config="using clang : : clang++ -fsanitize=address -Werror --std=c++17 ;" - - compiler: clang - env: | - label="clang C++11"; - user_config="using clang : : clang++ -fsanitize=address -Werror --std=c++11 ;" + label="clang C++11/17"; + user_config="using clang : : clang++ -fsanitize=address -Werror ;" + CXXSTD=11,17 # sanitized=address not available for 32-bit clang on travis. - compiler: clang env: | @@ -98,5 +92,5 @@ after_success: script: - cd ${TRAVIS_BUILD_DIR}/test - - bjam -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include + - bjam cxxstd=$CXXSTD -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include - xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml From 9f2063846b054b6372a515f6cec739c64b9d98bc Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 6 Jan 2018 13:38:56 +0000 Subject: [PATCH 23/50] Build b2 from the source snapshot --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 40561811..1340ec08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,6 @@ language: c++ addons: apt: packages: - - libboost-tools-dev - libxml2-utils - g++-multilib @@ -86,11 +85,15 @@ before_script: tar -xjf $HOME/download/boost.tar.bz2 mv * ${BOOST_ROOT} - rm -r ${BOOST_ROOT}/boost/unordered + - cd ${BOOST_ROOT}/tools/build + - mkdir ${HOME}/opt + - ./bootstrap.sh + - ./b2 install --prefix=$HOME/opt after_success: if [ -n $enable_coverage ]; then coveralls -r ${TRAVIS_BUILD_DIR} -b ${TRAVIS_BUILD_DIR}/test --gcov-options '\-lp' --include include/boost/unordered/ ; fi script: - cd ${TRAVIS_BUILD_DIR}/test - - bjam cxxstd=$CXXSTD -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include + - ${HOME}/opt/bin/b2 cxxstd=$CXXSTD -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include - xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml From d7ec41f4c60b513e9f2e764a851f1100915d72a4 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 6 Jan 2018 14:14:59 +0000 Subject: [PATCH 24/50] Add final use of CXXSTD in travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1340ec08..0fc13344 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,8 @@ matrix: - compiler: clang env: | label="clang 32 bit"; - user_config="using clang : : clang++ -m32 -Werror --std=c++03 ;" + user_config="using clang : : clang++ -m32 -Werror ;" + CXXSTD=03 before_install: - if [ -n $enable_coverage ]; then pip install --user cpp-coveralls; fi From c8facc99a7a567693cd5c630d42aa3588e8b73e9 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 6 Jan 2018 14:25:38 +0000 Subject: [PATCH 25/50] Run concurrent test processes in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0fc13344..5c205e53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -96,5 +96,5 @@ after_success: script: - cd ${TRAVIS_BUILD_DIR}/test - - ${HOME}/opt/bin/b2 cxxstd=$CXXSTD -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include + - ${HOME}/opt/bin/b2 -j 3 cxxstd=$CXXSTD -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include - xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml From ea28a3f98e951b3a274fb0e79741c3af2cbe63df Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 8 Jan 2018 10:57:28 +0000 Subject: [PATCH 26/50] Fix conversion to bool warning --- include/boost/unordered/detail/implementation.hpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index c3afa7fa..18ba03bd 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -2845,27 +2845,31 @@ namespace boost { } private: - void construct_functions(bool which, H const& hf, P const& eq) + void construct_functions(unsigned char which, H const& hf, P const& eq) { + BOOST_ASSERT(!(which & 2)); new ((void*)&funcs_[which]) function_pair(hf, eq); } - void construct_functions(bool which, function_pair const& f, + void construct_functions(unsigned char which, function_pair const& f, boost::unordered::detail::false_type = boost::unordered::detail::false_type()) { + BOOST_ASSERT(!(which & 2)); new ((void*)&funcs_[which]) function_pair(f); } - void construct_functions( - bool which, function_pair& f, boost::unordered::detail::true_type) + void construct_functions(unsigned char which, function_pair& f, + boost::unordered::detail::true_type) { + BOOST_ASSERT(!(which & 2)); new ((void*)&funcs_[which]) function_pair(f, boost::unordered::detail::move_tag()); } - void destroy_functions(bool which) + void destroy_functions(unsigned char which) { + BOOST_ASSERT(!(which & 2)); boost::unordered::detail::func::destroy( (function_pair*)(&funcs_[which])); } From 00a4185cf1875e8c3a864a2188f37e3aa1f2b2fd Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 8 Jan 2018 10:58:09 +0000 Subject: [PATCH 27/50] Reformat --- include/boost/unordered/detail/implementation.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 18ba03bd..e26f353b 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -3256,12 +3256,14 @@ namespace boost { // Not nothrow swappable void swap(table& x, false_type) { - if (this == &x) { return; } + if (this == &x) { + return; + } this->construct_spare_functions(x.current_functions()); - BOOST_TRY { - x.construct_spare_functions(this->current_functions()); - } BOOST_CATCH(...) { + BOOST_TRY { x.construct_spare_functions(this->current_functions()); } + BOOST_CATCH(...) + { this->cleanup_spare_functions(); BOOST_RETHROW } From d55c9565abd10ad0cd009c0dde23188943047572 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 10 Jan 2018 09:58:08 +0000 Subject: [PATCH 28/50] No template arguments in BOOST_MOVABLE_BUT_NOT_COPYABLE Was causing errors on Visual C++ 7.1. --- include/boost/unordered/detail/implementation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index e26f353b..48ef9beb 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -801,7 +801,7 @@ namespace boost { template class optional { - BOOST_MOVABLE_BUT_NOT_COPYABLE(optional) + BOOST_MOVABLE_BUT_NOT_COPYABLE(optional) boost::unordered::detail::value_base value_; bool has_value_; From dea525b2b7cab6f57893583fc1e8c1fa69474186 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 10 Jan 2018 11:35:22 +0000 Subject: [PATCH 29/50] Suppress msvc waring "conditional expression is constant" --- include/boost/unordered/unordered_map.hpp | 8 +++++--- include/boost/unordered/unordered_set.hpp | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 340bb5ef..f81213c3 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -27,9 +27,11 @@ #if defined(BOOST_MSVC) #pragma warning(push) #if BOOST_MSVC >= 1400 -#pragma warning(disable : 4396) // the inline specifier cannot be used when a -// friend declaration refers to a specialization -// of a function template +// conditional expression is constant +#pragma warning(disable : 4127) +// the inline specifier cannot be used when a friend declaration refers to a +// specialization of a function template +#pragma warning(disable : 4396) #endif #endif diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index f83c3526..865c7da4 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -26,9 +26,11 @@ #if defined(BOOST_MSVC) #pragma warning(push) #if BOOST_MSVC >= 1400 -#pragma warning(disable : 4396) // the inline specifier cannot be used when a -// friend declaration refers to a specialization -// of a function template +// conditional expression is constant +#pragma warning(disable : 4127) +// the inline specifier cannot be used when a friend declaration refers to a +// specialization of a function template +#pragma warning(disable : 4396) #endif #endif From f3476de893010959c8918970e85c4c6e47d0e236 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 10 Jan 2018 11:35:42 +0000 Subject: [PATCH 30/50] Some explicit casts to avoid warnings on old GCC --- include/boost/unordered/detail/implementation.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 48ef9beb..546bd7fa 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -2832,7 +2832,7 @@ namespace boost { void cleanup_spare_functions() { if (current_ & 2) { - current_ &= 1; + current_ = static_cast(current_ & 1); destroy_functions(current_ ^ 1); } } @@ -2840,7 +2840,7 @@ namespace boost { void switch_functions() { BOOST_ASSERT(current_ & 2); - destroy_functions(current_ & 1); + destroy_functions(static_cast(current_ & 1)); current_ ^= 3; } From a477d70f32736c1ff010e5cadd6489109543d664 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 10 Jan 2018 11:46:13 +0000 Subject: [PATCH 31/50] Add explicit failure for noexcept_tests on gcc + fix description for Visual C++ 7.1 --- meta/explicit-failures-markup.xml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/meta/explicit-failures-markup.xml b/meta/explicit-failures-markup.xml index 7ab7ce7e..4a49114a 100644 --- a/meta/explicit-failures-markup.xml +++ b/meta/explicit-failures-markup.xml @@ -17,11 +17,22 @@ - 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. + 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. - + + + + + + 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. + + + From ce0f16f32864575f8bb6783efab23eda1148b86a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 10 Jan 2018 15:14:50 +0000 Subject: [PATCH 32/50] Missing copyright messages --- meta/explicit-failures-markup.xml | 6 ++++++ test/exception/merge_exception_tests.cpp | 5 +++++ test/unordered/deduction_tests.cpp | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/meta/explicit-failures-markup.xml b/meta/explicit-failures-markup.xml index 4a49114a..25a19e3d 100644 --- a/meta/explicit-failures-markup.xml +++ b/meta/explicit-failures-markup.xml @@ -1,4 +1,10 @@ + diff --git a/test/exception/merge_exception_tests.cpp b/test/exception/merge_exception_tests.cpp index 4f5034bc..2cf7faf4 100644 --- a/test/exception/merge_exception_tests.cpp +++ b/test/exception/merge_exception_tests.cpp @@ -1,3 +1,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) + #include "../helpers/exception_test.hpp" #include "../helpers/invariants.hpp" #include "../helpers/metafunctions.hpp" diff --git a/test/unordered/deduction_tests.cpp b/test/unordered/deduction_tests.cpp index f1e14c94..673c0609 100644 --- a/test/unordered/deduction_tests.cpp +++ b/test/unordered/deduction_tests.cpp @@ -1,3 +1,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) + #include #include #include From 72fb9c7c96147aa9e58ad5d7843a16c0bc87ba4b Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 13 Jan 2018 20:31:45 +0000 Subject: [PATCH 33/50] Suppress warnings in noexcept_tests --- test/unordered/noexcept_tests.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/unordered/noexcept_tests.cpp b/test/unordered/noexcept_tests.cpp index 84bb404e..4a28ce18 100644 --- a/test/unordered/noexcept_tests.cpp +++ b/test/unordered/noexcept_tests.cpp @@ -12,6 +12,12 @@ #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. @@ -310,4 +316,8 @@ namespace noexcept_tests { } } +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + RUN_TESTS() From df8fbca007ca6f7bc97dbf4a5aa8c74a586c21da Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 13 Jan 2018 20:31:45 +0000 Subject: [PATCH 34/50] Double brackets for BOOST_STATIC_ASSERT --- test/unordered/node_handle_tests.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unordered/node_handle_tests.cpp b/test/unordered/node_handle_tests.cpp index a8e2fa28..a750cc72 100644 --- a/test/unordered/node_handle_tests.cpp +++ b/test/unordered/node_handle_tests.cpp @@ -249,8 +249,8 @@ void insert_node_handle_unique(Container1& c1, Container2& c2) { typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; - BOOST_STATIC_ASSERT(boost::is_same::value); + BOOST_STATIC_ASSERT((boost::is_same::value)); typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type insert_return_type1; @@ -294,8 +294,8 @@ void insert_node_handle_unique2(Container1& c1, Container2& c2) { typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; - BOOST_STATIC_ASSERT(boost::is_same::value); + BOOST_STATIC_ASSERT((boost::is_same::value)); // typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type // insert_return_type1; @@ -328,8 +328,8 @@ void insert_node_handle_equiv(Container1& c1, Container2& c2) { typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; - BOOST_STATIC_ASSERT(boost::is_same::value); + BOOST_STATIC_ASSERT((boost::is_same::value)); typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1; typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2; From 57492c1a94e9683d72c291ed16d758e36afde909 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 13 Jan 2018 20:31:45 +0000 Subject: [PATCH 35/50] Make allocator comparison const in allocator_traits test --- test/unordered/allocator_traits.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unordered/allocator_traits.cpp b/test/unordered/allocator_traits.cpp index c6b06f85..476205b7 100644 --- a/test/unordered/allocator_traits.cpp +++ b/test/unordered/allocator_traits.cpp @@ -36,8 +36,8 @@ { \ return (std::numeric_limits::max)(); \ } \ - bool operator==(name const&) { return true; } \ - bool operator!=(name const&) { return false; } \ + bool operator==(name const&) const { return true; } \ + bool operator!=(name const&) const { return false; } \ /**/ #define ALLOCATOR_METHODS_TYPEDEFS(name) \ From e64c5b34df7f7a2b3df32c1e6afa614096734860 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 17 Jan 2018 10:22:49 +0000 Subject: [PATCH 36/50] Try to fix insert_exception_tests on Visual C++ 7.1 It doesn't seem to like the nested template structs. If this doesn't work, I'll try moving them into the top level. --- test/exception/insert_exception_tests.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/exception/insert_exception_tests.cpp b/test/exception/insert_exception_tests.cpp index f0e55ae7..57314a6e 100644 --- a/test/exception/insert_exception_tests.cpp +++ b/test/exception/insert_exception_tests.cpp @@ -162,7 +162,8 @@ struct insert_lvalue_pos_type template friend impl generate(insert_lvalue_pos_type, T& x) { - return impl(x); + impl r(x); + return r; } } insert_lvalue_pos; @@ -214,7 +215,8 @@ struct emplace_lvalue_pos_type template friend impl generate(emplace_lvalue_pos_type, T& x) { - return impl(x); + impl r(x); + return r; } } emplace_lvalue_pos; From dc9faddf223a622a001c4b3a9790e12312be4cac Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 17 Jan 2018 10:30:20 +0000 Subject: [PATCH 37/50] Try to fix constructor_tests on Visual C++ 7.1 I'm really not sure why it fails to compile, the error message isn't very helpful. I assume it might be because allocator1 has an explicit default constructor, so I tried making it implicit. --- test/objects/test.hpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/objects/test.hpp b/test/objects/test.hpp index 8ea6d2de..8659eae6 100644 --- a/test/objects/test.hpp +++ b/test/objects/test.hpp @@ -354,7 +354,12 @@ namespace test { typedef allocator1 other; }; - explicit allocator1(int t = 0) : tag_(t) + allocator1() : tag_(0) + { + detail::tracker.allocator_ref(); + } + + explicit allocator1(int t) : tag_(t) { detail::tracker.allocator_ref(); } @@ -601,7 +606,12 @@ namespace test { typedef allocator2 other; }; - explicit allocator2(int t = 0) : tag_(t) + allocator2() : tag_(0) + { + detail::tracker.allocator_ref(); + } + + explicit allocator2(int t) : tag_(t) { detail::tracker.allocator_ref(); } From f7665a274305133dfc754c5893b09493eb3da565 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 20 Jan 2018 08:49:40 +0000 Subject: [PATCH 38/50] Another attempt to fix insert_exception_tests on Visual C++ 7.1 Try extracting the nested template structs. --- test/exception/insert_exception_tests.cpp | 60 +++++++++++------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/test/exception/insert_exception_tests.cpp b/test/exception/insert_exception_tests.cpp index 57314a6e..1043a3fb 100644 --- a/test/exception/insert_exception_tests.cpp +++ b/test/exception/insert_exception_tests.cpp @@ -146,24 +146,24 @@ struct insert_lvalue_end_type : inserter_base } } insert_lvalue_end; +template struct insert_lvalue_pos_type_impl : inserter_base +{ + typename T::iterator pos; + + insert_lvalue_pos_type_impl(T& x) : pos(x.begin()) {} + + template void operator()(T& x, Iterator it) + { + pos = get_iterator(x.insert(pos, *it)); + } +}; + struct insert_lvalue_pos_type { - template struct impl : inserter_base + template + friend insert_lvalue_pos_type_impl generate(insert_lvalue_pos_type, T& x) { - typename T::iterator pos; - - impl(T& x) : pos(x.begin()) {} - - template void operator()(T& x, Iterator it) - { - pos = get_iterator(x.insert(pos, *it)); - } - }; - - template friend impl generate(insert_lvalue_pos_type, T& x) - { - impl r(x); - return r; + return insert_lvalue_pos_type_impl(x); } } insert_lvalue_pos; @@ -199,24 +199,24 @@ struct emplace_lvalue_end_type : inserter_base } } emplace_lvalue_end; +template struct emplace_lvalue_pos_type_impl : inserter_base +{ + typename T::iterator pos; + + emplace_lvalue_pos_type_impl(T& x) : pos(x.begin()) {} + + template void operator()(T& x, Iterator it) + { + pos = get_iterator(x.emplace_hint(pos, *it)); + } +}; + struct emplace_lvalue_pos_type { - template struct impl : inserter_base + template + friend emplace_lvalue_pos_type_impl generate(emplace_lvalue_pos_type, T& x) { - typename T::iterator pos; - - impl(T& x) : pos(x.begin()) {} - - template void operator()(T& x, Iterator it) - { - pos = get_iterator(x.emplace_hint(pos, *it)); - } - }; - - template friend impl generate(emplace_lvalue_pos_type, T& x) - { - impl r(x); - return r; + return emplace_lvalue_pos_type_impl(x); } } emplace_lvalue_pos; From 1cc3f680e8317f91dbba918443c142cb0a9f66f5 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 20 Jan 2018 11:49:07 +0000 Subject: [PATCH 39/50] Fix a couple more explicit default constructors for Visual C++ 7.1 --- test/objects/test.hpp | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/test/objects/test.hpp b/test/objects/test.hpp index 8659eae6..7ce21fa9 100644 --- a/test/objects/test.hpp +++ b/test/objects/test.hpp @@ -189,7 +189,9 @@ namespace test { int type_; public: - explicit hash(int t = 0) : type_(t) {} + hash() : type_(0) {} + + explicit hash(int t) : type_(t) {} std::size_t operator()(object const& x) const { @@ -298,7 +300,9 @@ namespace test { int type_; public: - explicit equal_to(int t = 0) : type_(t) {} + equal_to() : type_(0) {} + + explicit equal_to(int t) : type_(t) {} bool operator()(object const& x1, object const& x2) const { @@ -354,15 +358,9 @@ namespace test { typedef allocator1 other; }; - allocator1() : tag_(0) - { - detail::tracker.allocator_ref(); - } + allocator1() : tag_(0) { detail::tracker.allocator_ref(); } - explicit allocator1(int t) : tag_(t) - { - detail::tracker.allocator_ref(); - } + explicit allocator1(int t) : tag_(t) { detail::tracker.allocator_ref(); } template allocator1(allocator1 const& x) : tag_(x.tag_) { @@ -606,15 +604,9 @@ namespace test { typedef allocator2 other; }; - allocator2() : tag_(0) - { - detail::tracker.allocator_ref(); - } + allocator2() : tag_(0) { detail::tracker.allocator_ref(); } - explicit allocator2(int t) : tag_(t) - { - detail::tracker.allocator_ref(); - } + explicit allocator2(int t) : tag_(t) { detail::tracker.allocator_ref(); } template allocator2(allocator2 const& x) : tag_(x.tag_) { From ea599a66b7a053388922e75c17fd9af051021695 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 23 Jan 2018 15:40:58 +0000 Subject: [PATCH 40/50] Disable 'conditional expression is constant' on older Visual C++ --- include/boost/unordered/unordered_map.hpp | 2 +- include/boost/unordered/unordered_set.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index f81213c3..acaf99c6 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -26,9 +26,9 @@ #if defined(BOOST_MSVC) #pragma warning(push) -#if BOOST_MSVC >= 1400 // conditional expression is constant #pragma warning(disable : 4127) +#if BOOST_MSVC >= 1400 // the inline specifier cannot be used when a friend declaration refers to a // specialization of a function template #pragma warning(disable : 4396) diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 865c7da4..92af2c01 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -25,9 +25,9 @@ #if defined(BOOST_MSVC) #pragma warning(push) -#if BOOST_MSVC >= 1400 // conditional expression is constant #pragma warning(disable : 4127) +#if BOOST_MSVC >= 1400 // the inline specifier cannot be used when a friend declaration refers to a // specialization of a function template #pragma warning(disable : 4396) From 66533ace802a5fe5db10eade35ad9d5cfba1ee75 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 26 Jan 2018 17:43:06 +0000 Subject: [PATCH 41/50] Add `element_type` to nodes, so that pointer_traits will work Might be better to change the template signature of iterators, but that would be a disruptive change to make at the moment. --- .../boost/unordered/detail/implementation.hpp | 4 + test/unordered/compile_tests.hpp | 73 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 546bd7fa..44bff527 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -2260,6 +2260,7 @@ namespace boost { std::size_t bucket_count_; public: + typedef typename Node::value_type element_type; typedef typename Node::value_type value_type; typedef value_type* pointer; typedef value_type& reference; @@ -2316,6 +2317,7 @@ namespace boost { std::size_t bucket_count_; public: + typedef typename Node::value_type const element_type; typedef typename Node::value_type value_type; typedef value_type const* pointer; typedef value_type const& reference; @@ -2384,6 +2386,7 @@ namespace boost { node_pointer node_; public: + typedef typename Node::value_type element_type; typedef typename Node::value_type value_type; typedef value_type* pointer; typedef value_type& reference; @@ -2439,6 +2442,7 @@ namespace boost { node_pointer node_; public: + typedef typename Node::value_type const element_type; typedef typename Node::value_type value_type; typedef value_type const* pointer; typedef value_type const& reference; diff --git a/test/unordered/compile_tests.hpp b/test/unordered/compile_tests.hpp index c3aa9a87..588414ec 100644 --- a/test/unordered/compile_tests.hpp +++ b/test/unordered/compile_tests.hpp @@ -18,6 +18,7 @@ #include "../helpers/check_return_type.hpp" #include +#include #include #include #include @@ -280,6 +281,42 @@ template void unordered_set_test(X& r, Key const&) BOOST_STATIC_ASSERT( (boost::is_same::value)); + // pointer_traits + + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + + // pointer_traits + + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + + // pointer_traits + + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + + // pointer_traits + + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; typedef BOOST_DEDUCED_TYPENAME node_type::value_type node_value_type; BOOST_STATIC_ASSERT((boost::is_same::value)); @@ -325,6 +362,42 @@ void unordered_map_test(X& r, Key const& k, T const& v) BOOST_STATIC_ASSERT( (boost::is_same::value)); + // pointer_traits + + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + + // pointer_traits + + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + + // pointer_traits + + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + + // pointer_traits + + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; typedef BOOST_DEDUCED_TYPENAME node_type::key_type node_key_type; typedef BOOST_DEDUCED_TYPENAME node_type::mapped_type node_mapped_type; From 0d340538703011a451da1b7f87f95c54f251dcc1 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 26 Jan 2018 17:44:42 +0000 Subject: [PATCH 42/50] Use boost::to_address in node_handle_tests --- test/unordered/node_handle_tests.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/unordered/node_handle_tests.cpp b/test/unordered/node_handle_tests.cpp index a750cc72..f1b9c965 100644 --- a/test/unordered/node_handle_tests.cpp +++ b/test/unordered/node_handle_tests.cpp @@ -11,6 +11,7 @@ #include "../helpers/helpers.hpp" #include "../helpers/metafunctions.hpp" #include "../helpers/test.hpp" +#include #include #include #include @@ -268,14 +269,14 @@ void insert_node_handle_unique(Container1& c1, Container2& c2) while (!c1.empty()) { value_type v = *c1.begin(); - value_type const* v_ptr = boost::addressof(*c1.begin()); + value_type const* v_ptr = boost::to_address(c1.begin()); std::size_t count = c2.count(test::get_key(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(v)), count + 1); BOOST_TEST(r.position != c2.end()); - BOOST_TEST(boost::addressof(*r.position) == v_ptr); + BOOST_TEST(boost::to_address(r.position) == v_ptr); BOOST_TEST(!r.node); } else { BOOST_TEST(!r.inserted); @@ -304,13 +305,13 @@ void insert_node_handle_unique2(Container1& c1, Container2& c2) while (!c1.empty()) { value_type v = *c1.begin(); - value_type const* v_ptr = boost::addressof(*c1.begin()); + value_type const* v_ptr = boost::to_address(c1.begin()); std::size_t count = c2.count(test::get_key(v)); insert_return_type2 r = c2.insert(c1.extract(test::get_key(v))); if (r.inserted) { BOOST_TEST_EQ(c2.count(test::get_key(v)), count + 1); BOOST_TEST(r.position != c2.end()); - BOOST_TEST(boost::addressof(*r.position) == v_ptr); + BOOST_TEST(boost::to_address(r.position) == v_ptr); BOOST_TEST(!r.node); } else { BOOST_TEST_EQ(c2.count(test::get_key(v)), count); @@ -341,12 +342,12 @@ void insert_node_handle_equiv(Container1& c1, Container2& c2) while (!c1.empty()) { value_type v = *c1.begin(); - value_type const* v_ptr = boost::addressof(*c1.begin()); + value_type const* v_ptr = boost::to_address(c1.begin()); std::size_t count = c2.count(test::get_key(v)); iterator2 r = c2.insert(c1.extract(c1.begin())); BOOST_TEST_EQ(c2.count(test::get_key(v)), count + 1); BOOST_TEST(r != c2.end()); - BOOST_TEST(boost::addressof(*r) == v_ptr); + BOOST_TEST(boost::to_address(r) == v_ptr); } } From ca9e9584ba71d688b0db7221a800c42c7f77f9d4 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 26 Jan 2018 18:03:56 +0000 Subject: [PATCH 43/50] Test on appveyor --- .appveyor.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000..e699c6e6 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,33 @@ +# Copyright 2017 Daniel James +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +version: 1.0.{build}-{branch} + +shallow_clone: true + +environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + TOOLSET: msvc-10.0,msvc-11.0,msvc-12.0 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + TOOLSET: msvc-14.0 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + TOOLSET: msvc-14.1 + +install: + - cd c:\projects + - curl -sSL -o boost.7z https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.7z + - 7z x boost.7z + - set BOOST_ROOT=c:\projects\boost_1_66_0 + - rd /s /q %BOOST_ROOT%\boost\unordered + - cd %BOOST_ROOT%\tools\build + - cmd /c bootstrap + - cd %APPVEYOR_BUILD_FOLDER% + - echo. 2>Jamroot.jam + +build: off + +test_script: + - cd %APPVEYOR_BUILD_FOLDER%\test + - cmd /c %BOOST_ROOT%\tools\build\b2 -j 3 toolset=%TOOLSET% include=%APPVEYOR_BUILD_FOLDER%\include include=%BOOST_ROOT% From ddf302fcc26d4dfb5176b45182fdc83f62859718 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 26 Jan 2018 18:59:11 +0000 Subject: [PATCH 44/50] Use `boost::to_pointer` instead of `pointer<..>::get` To get C++20 style recursive calls to `operator->`. --- .../boost/unordered/detail/implementation.hpp | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 44bff527..f041f7fd 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -553,21 +554,6 @@ namespace boost { { template convert_from_anything(T const&); }; - - // Get a pointer from a smart pointer, a bit simpler than pointer_traits - // as we already know the pointer type that we want. - template struct pointer - { - template static T* get(Ptr const& x) - { - return static_cast(x.operator->()); - } - - template static T* get(T2* x) - { - return static_cast(x); - } - }; } } } @@ -1814,7 +1800,7 @@ namespace boost { BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { boost::unordered::detail::func::construct_from_tuple( - alloc, boost::addressof(address->first), boost::forward(a1)); + alloc, boost::addressof (address->first), boost::forward(a1)); BOOST_TRY { boost::unordered::detail::func::construct_from_tuple( @@ -2002,7 +1988,7 @@ namespace boost { template node_constructor::~node_constructor() { if (node_) { - boost::unordered::detail::func::destroy(pointer::get(node_)); + boost::unordered::detail::func::destroy(boost::to_pointer(node_)); node_allocator_traits::deallocate(alloc_, node_, 1); } } @@ -2011,7 +1997,7 @@ namespace boost { { BOOST_ASSERT(!node_); node_ = node_allocator_traits::allocate(alloc_, 1); - new (pointer::get(node_)) node(); + new ((void*) boost::to_pointer(node_)) node(); } template struct node_tmp @@ -2042,7 +2028,7 @@ namespace boost { if (node_) { BOOST_UNORDERED_CALL_DESTROY( node_allocator_traits, alloc_, node_->value_ptr()); - boost::unordered::detail::func::destroy(pointer::get(node_)); + boost::unordered::detail::func::destroy(boost::to_pointer(node_)); node_allocator_traits::deallocate(alloc_, node_, 1); } } @@ -2574,7 +2560,7 @@ namespace boost { BOOST_UNORDERED_CALL_DESTROY( node_allocator_traits, constructor_.alloc_, p->value_ptr()); - boost::unordered::detail::func::destroy(pointer::get(p)); + boost::unordered::detail::func::destroy(boost::to_pointer(p)); node_allocator_traits::deallocate(constructor_.alloc_, p, 1); } } @@ -3234,9 +3220,9 @@ namespace boost { bucket_pointer end = buckets_ + static_cast(new_count); for (bucket_pointer i = buckets_; i != end; ++i) { - new (pointer::get(i)) bucket(); + new ((void*) boost::to_pointer(i)) bucket(); } - new (pointer::get(end)) bucket(dummy_node); + new ((void*) boost::to_pointer(end)) bucket(dummy_node); } //////////////////////////////////////////////////////////////////////// @@ -3364,7 +3350,7 @@ namespace boost { { BOOST_UNORDERED_CALL_DESTROY( node_allocator_traits, node_alloc(), n->value_ptr()); - boost::unordered::detail::func::destroy(pointer::get(n)); + boost::unordered::detail::func::destroy(boost::to_pointer(n)); node_allocator_traits::deallocate(node_alloc(), n, 1); } @@ -3376,7 +3362,7 @@ namespace boost { if (bucket::extra_node) { node_pointer next = next_node(n); - boost::unordered::detail::func::destroy(pointer::get(n)); + boost::unordered::detail::func::destroy(boost::to_pointer(n)); node_allocator_traits::deallocate(node_alloc(), n, 1); n = next; } @@ -3398,7 +3384,7 @@ namespace boost { { bucket_pointer end = get_bucket_pointer(bucket_count_ + 1); for (bucket_pointer it = buckets_; it != end; ++it) { - boost::unordered::detail::func::destroy(pointer::get(it)); + boost::unordered::detail::func::destroy(boost::to_pointer(it)); } bucket_allocator_traits::deallocate( From cdb0229cf2d7da19c5a463b52907ac31cfee0b00 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 26 Jan 2018 20:01:29 +0000 Subject: [PATCH 45/50] Use snapshot to get latest pointer_traits --- .appveyor.yml | 4 ++-- .travis.yml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index e699c6e6..eed13281 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,9 +17,9 @@ environment: install: - cd c:\projects - - curl -sSL -o boost.7z https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.7z + - curl -sSL -o boost.7z https://dl.bintray.com/boostorg/master/boost_1_67_0-snapshot.7z - 7z x boost.7z - - set BOOST_ROOT=c:\projects\boost_1_66_0 + - set BOOST_ROOT=c:\projects\boost_1_67_0 - rd /s /q %BOOST_ROOT%\boost\unordered - cd %BOOST_ROOT%\tools\build - cmd /c bootstrap diff --git a/.travis.yml b/.travis.yml index 5c205e53..554bb82e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,7 +62,8 @@ before_script: snapshot=develop fi else - snapshot=stable + #snapshot=stable + snapshot=master fi # Set download_url for snapshot From c01a8c4629e205067bfd7e24b08c47378d20ae6c Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 26 Jan 2018 20:25:09 +0000 Subject: [PATCH 46/50] Oops, it's boost::to_address, no boost::to_pointer --- .../boost/unordered/detail/implementation.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index f041f7fd..d45ca246 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -1988,7 +1988,7 @@ namespace boost { template node_constructor::~node_constructor() { if (node_) { - boost::unordered::detail::func::destroy(boost::to_pointer(node_)); + boost::unordered::detail::func::destroy(boost::to_address(node_)); node_allocator_traits::deallocate(alloc_, node_, 1); } } @@ -1997,7 +1997,7 @@ namespace boost { { BOOST_ASSERT(!node_); node_ = node_allocator_traits::allocate(alloc_, 1); - new ((void*) boost::to_pointer(node_)) node(); + new ((void*) boost::to_address(node_)) node(); } template struct node_tmp @@ -2028,7 +2028,7 @@ namespace boost { if (node_) { BOOST_UNORDERED_CALL_DESTROY( node_allocator_traits, alloc_, node_->value_ptr()); - boost::unordered::detail::func::destroy(boost::to_pointer(node_)); + boost::unordered::detail::func::destroy(boost::to_address(node_)); node_allocator_traits::deallocate(alloc_, node_, 1); } } @@ -2560,7 +2560,7 @@ namespace boost { BOOST_UNORDERED_CALL_DESTROY( node_allocator_traits, constructor_.alloc_, p->value_ptr()); - boost::unordered::detail::func::destroy(boost::to_pointer(p)); + boost::unordered::detail::func::destroy(boost::to_address(p)); node_allocator_traits::deallocate(constructor_.alloc_, p, 1); } } @@ -3220,9 +3220,9 @@ namespace boost { bucket_pointer end = buckets_ + static_cast(new_count); for (bucket_pointer i = buckets_; i != end; ++i) { - new ((void*) boost::to_pointer(i)) bucket(); + new ((void*) boost::to_address(i)) bucket(); } - new ((void*) boost::to_pointer(end)) bucket(dummy_node); + new ((void*) boost::to_address(end)) bucket(dummy_node); } //////////////////////////////////////////////////////////////////////// @@ -3350,7 +3350,7 @@ namespace boost { { BOOST_UNORDERED_CALL_DESTROY( node_allocator_traits, node_alloc(), n->value_ptr()); - boost::unordered::detail::func::destroy(boost::to_pointer(n)); + boost::unordered::detail::func::destroy(boost::to_address(n)); node_allocator_traits::deallocate(node_alloc(), n, 1); } @@ -3362,7 +3362,7 @@ namespace boost { if (bucket::extra_node) { node_pointer next = next_node(n); - boost::unordered::detail::func::destroy(boost::to_pointer(n)); + boost::unordered::detail::func::destroy(boost::to_address(n)); node_allocator_traits::deallocate(node_alloc(), n, 1); n = next; } @@ -3384,7 +3384,7 @@ namespace boost { { bucket_pointer end = get_bucket_pointer(bucket_count_ + 1); for (bucket_pointer it = buckets_; it != end; ++it) { - boost::unordered::detail::func::destroy(boost::to_pointer(it)); + boost::unordered::detail::func::destroy(boost::to_address(it)); } bucket_allocator_traits::deallocate( From 09be9bae046d8f795bad286795bb2ca8d0f77139 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 27 Jan 2018 09:38:19 +0000 Subject: [PATCH 47/50] Use boost::is_nothrow_swappable, now that it's available everywhere --- .../boost/unordered/detail/implementation.hpp | 28 ++---- include/boost/unordered/unordered_map.hpp | 16 ++-- include/boost/unordered/unordered_set.hpp | 16 ++-- test/unordered/compile_tests.hpp | 93 ++++++++++++------- test/unordered/noexcept_tests.cpp | 13 +-- 5 files changed, 86 insertions(+), 80 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index d45ca246..9914683f 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -35,12 +35,11 @@ #include #include #include -#include #include #include #include +#include #include -#include #include #include #include @@ -740,19 +739,6 @@ namespace boost { #pragma warning(pop) #endif - //////////////////////////////////////////////////////////////////////////// - // is_nothrow_swappable - // - // TODO: Replace this very basic implementation when the full type_traits - // implementation is available. - - template - struct is_nothrow_swappable - : boost::integral_constant::value && !boost::is_const::value> - { - }; - ////////////////////////////////////////////////////////////////////////// // value_base // @@ -1800,7 +1786,7 @@ namespace boost { BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { boost::unordered::detail::func::construct_from_tuple( - alloc, boost::addressof (address->first), boost::forward(a1)); + alloc, boost::addressof(address->first), boost::forward(a1)); BOOST_TRY { boost::unordered::detail::func::construct_from_tuple( @@ -1997,7 +1983,7 @@ namespace boost { { BOOST_ASSERT(!node_); node_ = node_allocator_traits::allocate(alloc_, 1); - new ((void*) boost::to_address(node_)) node(); + new ((void*)boost::to_address(node_)) node(); } template struct node_tmp @@ -2756,8 +2742,8 @@ namespace boost { boost::is_nothrow_move_constructible::value && boost::is_nothrow_move_constructible

::value; static const bool nothrow_swappable = - boost::unordered::detail::is_nothrow_swappable::value && - boost::unordered::detail::is_nothrow_swappable

::value; + boost::is_nothrow_swappable::value && + boost::is_nothrow_swappable

::value; private: functions& operator=(functions const&); @@ -3220,9 +3206,9 @@ namespace boost { bucket_pointer end = buckets_ + static_cast(new_count); for (bucket_pointer i = buckets_; i != end; ++i) { - new ((void*) boost::to_address(i)) bucket(); + new ((void*)boost::to_address(i)) bucket(); } - new ((void*) boost::to_address(end)) bucket(dummy_node); + new ((void*)boost::to_address(end)) bucket(dummy_node); } //////////////////////////////////////////////////////////////////////// diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index acaf99c6..1910219c 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -717,8 +717,8 @@ namespace boost { void swap(unordered_map&) BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& - boost::unordered::detail::is_nothrow_swappable::value&& - boost::unordered::detail::is_nothrow_swappable

::value); + boost::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -1326,8 +1326,8 @@ namespace boost { void swap(unordered_multimap&) BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& - boost::unordered::detail::is_nothrow_swappable::value&& - boost::unordered::detail::is_nothrow_swappable

::value); + boost::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -1737,8 +1737,8 @@ namespace boost { template void unordered_map::swap(unordered_map& other) BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& - boost::unordered::detail::is_nothrow_swappable::value&& - boost::unordered::detail::is_nothrow_swappable

::value) + boost::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value) { table_.swap(other.table_); } @@ -2213,8 +2213,8 @@ namespace boost { template void unordered_multimap::swap(unordered_multimap& other) BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& - boost::unordered::detail::is_nothrow_swappable::value&& - boost::unordered::detail::is_nothrow_swappable

::value) + boost::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value) { table_.swap(other.table_); } diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 92af2c01..dfc24e85 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -443,8 +443,8 @@ namespace boost { void swap(unordered_set&) BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& - boost::unordered::detail::is_nothrow_swappable::value&& - boost::unordered::detail::is_nothrow_swappable

::value); + boost::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -990,8 +990,8 @@ namespace boost { void swap(unordered_multiset&) BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& - boost::unordered::detail::is_nothrow_swappable::value&& - boost::unordered::detail::is_nothrow_swappable

::value); + boost::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -1362,8 +1362,8 @@ namespace boost { template void unordered_set::swap(unordered_set& other) BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& - boost::unordered::detail::is_nothrow_swappable::value&& - boost::unordered::detail::is_nothrow_swappable

::value) + boost::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value) { table_.swap(other.table_); } @@ -1756,8 +1756,8 @@ namespace boost { template void unordered_multiset::swap(unordered_multiset& other) BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&& - boost::unordered::detail::is_nothrow_swappable::value&& - boost::unordered::detail::is_nothrow_swappable

::value) + boost::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value) { table_.swap(other.table_); } diff --git a/test/unordered/compile_tests.hpp b/test/unordered/compile_tests.hpp index 588414ec..691e4413 100644 --- a/test/unordered/compile_tests.hpp +++ b/test/unordered/compile_tests.hpp @@ -17,11 +17,12 @@ #endif #include "../helpers/check_return_type.hpp" -#include #include +#include #include #include #include +#include #include #include #include @@ -286,36 +287,47 @@ template void unordered_set_test(X& r, Key const&) BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::element_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::difference_type>::value)); // pointer_traits - BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::element_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::difference_type>::value)); // pointer_traits - BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::element_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::difference_type>::value)); // pointer_traits BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::element_type>::value)); BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::difference_type>::value)); typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; typedef BOOST_DEDUCED_TYPENAME node_type::value_type node_value_type; @@ -366,37 +378,48 @@ void unordered_map_test(X& r, Key const& k, T const& v) BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); - BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + BOOST_STATIC_ASSERT( + (boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::difference_type>::value)); // pointer_traits - BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::element_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::difference_type>::value)); // pointer_traits - BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); - BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT( + (boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::difference_type>::value)); // pointer_traits BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::element_type>::value)); BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + BOOST_DEDUCED_TYPENAME + boost::pointer_traits::difference_type>::value)); typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; typedef BOOST_DEDUCED_TYPENAME node_type::key_type node_key_type; diff --git a/test/unordered/noexcept_tests.cpp b/test/unordered/noexcept_tests.cpp index 4a28ce18..454e7c23 100644 --- a/test/unordered/noexcept_tests.cpp +++ b/test/unordered/noexcept_tests.cpp @@ -165,13 +165,12 @@ namespace noexcept_tests { !boost::is_nothrow_move_constructible::value); BOOST_TEST( !boost::is_nothrow_move_assignable::value); - BOOST_TEST(!boost::unordered::detail::is_nothrow_swappable< - hash_possible_exception>::value); + BOOST_TEST(!boost::is_nothrow_swappable::value); BOOST_TEST((!boost::is_nothrow_move_constructible< equal_to_nothrow >::value)); BOOST_TEST((!boost::is_nothrow_move_assignable< equal_to_nothrow >::value)); - BOOST_TEST((!boost::unordered::detail::is_nothrow_swappable< + BOOST_TEST((!boost::is_nothrow_swappable< equal_to_nothrow >::value)); have_is_nothrow_move = @@ -179,7 +178,7 @@ namespace noexcept_tests { have_is_nothrow_move_assign = boost::is_nothrow_move_assignable::value; have_is_nothrow_swap = - boost::unordered::detail::is_nothrow_swappable::value; + boost::is_nothrow_swappable::value; // Check that the traits work when expected. #if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && \ @@ -191,8 +190,7 @@ namespace noexcept_tests { #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_NOEXCEPT) && \ !defined(BOOST_NO_CXX11_DECLTYPE) && \ !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) -// TODO: Turn test on when unordered starts to use is_nothrow_swap -// BOOST_TEST(have_is_nothrow_swap); + BOOST_TEST(have_is_nothrow_swap); #endif BOOST_LIGHTWEIGHT_TEST_OSTREAM @@ -286,8 +284,7 @@ namespace noexcept_tests { throwing_set; if (have_is_nothrow_swap) { - BOOST_TEST( - boost::unordered::detail::is_nothrow_swappable::value); + BOOST_TEST(boost::is_nothrow_swappable::value); } throwing_test_exception = false; From cfd4bacc2c61f36803932bee65db9de5e3dcc9a0 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 27 Jan 2018 09:39:59 +0000 Subject: [PATCH 48/50] Stop using BOOST_DEDUCED_TYPENAME We no longer support any of the compilers that require it. I'd be very surprised if anything was working on them. --- test/exception/assign_exception_tests.cpp | 6 +- .../exception/constructor_exception_tests.cpp | 6 +- test/exception/erase_exception_tests.cpp | 3 +- test/exception/insert_exception_tests.cpp | 2 +- .../exception/move_assign_exception_tests.cpp | 6 +- test/exception/swap_exception_tests.cpp | 6 +- test/helpers/equivalent.hpp | 8 +- test/helpers/exception_test.hpp | 15 +- test/helpers/helpers.hpp | 4 +- test/helpers/input_iterator.hpp | 22 +- test/helpers/invariants.hpp | 23 +- test/helpers/metafunctions.hpp | 16 +- test/helpers/random_values.hpp | 10 +- test/helpers/strong.hpp | 2 +- test/helpers/tracker.hpp | 41 +-- test/unordered/assign_tests.cpp | 18 +- test/unordered/bucket_tests.cpp | 9 +- test/unordered/compile_tests.hpp | 300 ++++++++---------- test/unordered/constructor_tests.cpp | 39 ++- test/unordered/copy_tests.cpp | 18 +- test/unordered/erase_tests.cpp | 23 +- test/unordered/extract_tests.cpp | 11 +- test/unordered/find_tests.cpp | 30 +- test/unordered/insert_tests.cpp | 173 +++++----- test/unordered/load_factor_tests.cpp | 9 +- test/unordered/move_tests.cpp | 28 +- test/unordered/node_handle_tests.cpp | 55 ++-- test/unordered/rehash_tests.cpp | 3 +- test/unordered/simple_tests.cpp | 2 +- test/unordered/swap_tests.cpp | 6 +- test/unordered/unnecessary_copy_tests.cpp | 22 +- 31 files changed, 412 insertions(+), 504 deletions(-) diff --git a/test/exception/assign_exception_tests.cpp b/test/exception/assign_exception_tests.cpp index 05f22fa7..c62bf8ab 100644 --- a/test/exception/assign_exception_tests.cpp +++ b/test/exception/assign_exception_tests.cpp @@ -54,9 +54,9 @@ template struct assign_base : public test::exception_base test::random_values x_values, y_values; T x, y; - typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; - typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; - typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; + 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(), diff --git a/test/exception/constructor_exception_tests.cpp b/test/exception/constructor_exception_tests.cpp index d480accd..3dfebcef 100644 --- a/test/exception/constructor_exception_tests.cpp +++ b/test/exception/constructor_exception_tests.cpp @@ -172,9 +172,9 @@ template struct input_range_construct_test : public range, objects void run() const { - BOOST_DEDUCED_TYPENAME test::random_values::const_iterator - begin = this->values.begin(), - end = this->values.end(); + typename test::random_values::const_iterator begin = + this->values.begin(), + end = this->values.end(); T x(test::input_iterator(begin), test::input_iterator(end), 0, hash, equal_to, allocator); diff --git a/test/exception/erase_exception_tests.cpp b/test/exception/erase_exception_tests.cpp index dcd2dbd5..0f2c1eb6 100644 --- a/test/exception/erase_exception_tests.cpp +++ b/test/exception/erase_exception_tests.cpp @@ -38,8 +38,7 @@ template struct erase_by_key_test1 : public erase_test_base { void run(T& x) const { - typedef BOOST_DEDUCED_TYPENAME test::random_values::const_iterator - iterator; + typedef typename test::random_values::const_iterator iterator; for (iterator it = this->values.begin(), end = this->values.end(); it != end; ++it) { diff --git a/test/exception/insert_exception_tests.cpp b/test/exception/insert_exception_tests.cpp index 1043a3fb..79074c5e 100644 --- a/test/exception/insert_exception_tests.cpp +++ b/test/exception/insert_exception_tests.cpp @@ -18,7 +18,7 @@ test::seed_t initialize_seed(747373); template void rehash_prep(T& x) { using namespace std; - typedef BOOST_DEDUCED_TYPENAME T::size_type size_type; + typedef typename T::size_type size_type; x.max_load_factor(0.25); size_type bucket_count = x.bucket_count(); diff --git a/test/exception/move_assign_exception_tests.cpp b/test/exception/move_assign_exception_tests.cpp index b81bfe36..6beb6820 100644 --- a/test/exception/move_assign_exception_tests.cpp +++ b/test/exception/move_assign_exception_tests.cpp @@ -21,9 +21,9 @@ template struct move_assign_base : public test::exception_base test::random_values x_values, y_values; T x, y; - typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; - typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; - typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; + 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(), diff --git a/test/exception/swap_exception_tests.cpp b/test/exception/swap_exception_tests.cpp index b2bec836..1569e814 100644 --- a/test/exception/swap_exception_tests.cpp +++ b/test/exception/swap_exception_tests.cpp @@ -60,9 +60,9 @@ template struct swap_base : public test::exception_base const test::random_values x_values, y_values; const T initial_x, initial_y; - typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; - typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; - typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; + 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), diff --git a/test/helpers/equivalent.hpp b/test/helpers/equivalent.hpp index 5c1bfa82..bd27d8df 100644 --- a/test/helpers/equivalent.hpp +++ b/test/helpers/equivalent.hpp @@ -58,12 +58,12 @@ namespace test { template class unordered_equivalence_tester { - BOOST_DEDUCED_TYPENAME Container::size_type size_; - BOOST_DEDUCED_TYPENAME Container::hasher hasher_; - BOOST_DEDUCED_TYPENAME Container::key_equal key_equal_; + typename Container::size_type size_; + typename Container::hasher hasher_; + typename Container::key_equal key_equal_; float max_load_factor_; - typedef test::list value_list; + typedef test::list value_list; value_list values_; public: diff --git a/test/helpers/exception_test.hpp b/test/helpers/exception_test.hpp index d5272691..8984eee9 100644 --- a/test/helpers/exception_test.hpp +++ b/test/helpers/exception_test.hpp @@ -176,21 +176,18 @@ namespace test { DISABLE_EXCEPTIONS; test::check_instances check; test::scope = ""; - BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init()); - BOOST_DEDUCED_TYPENAME Test::strong_type strong; + typename Test::data_type x(test_.init()); + typename Test::strong_type strong; strong.store(x); try { ENABLE_EXCEPTIONS; - call_ignore_extra_parameters( - &Test::run, test_, x, strong); + call_ignore_extra_parameters(&Test::run, test_, x, strong); } catch (...) { try { DISABLE_EXCEPTIONS; - call_ignore_extra_parameters( + call_ignore_extra_parameters( &Test::check, test_, constant(x), constant(strong)); } catch (...) { exception_in_check_ = true; diff --git a/test/helpers/helpers.hpp b/test/helpers/helpers.hpp index 854ebfc7..146dea4d 100644 --- a/test/helpers/helpers.hpp +++ b/test/helpers/helpers.hpp @@ -11,7 +11,7 @@ namespace test { template struct get_key_impl { - typedef BOOST_DEDUCED_TYPENAME Container::key_type key_type; + typedef typename Container::key_type key_type; static key_type const& get_key(key_type const& x) { return x; } @@ -30,7 +30,7 @@ namespace test { }; template - inline BOOST_DEDUCED_TYPENAME Container::key_type const& get_key(T const& x) + inline typename Container::key_type const& get_key(T const& x) { return get_key_impl::get_key(x); } diff --git a/test/helpers/input_iterator.hpp b/test/helpers/input_iterator.hpp index ab1a818b..7a938a50 100644 --- a/test/helpers/input_iterator.hpp +++ b/test/helpers/input_iterator.hpp @@ -12,7 +12,7 @@ namespace test { template struct proxy { - typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type; + typedef typename Iterator::value_type value_type; explicit proxy(value_type const& v) : v_(v) {} proxy(proxy const& x) : v_(x.v_) {} @@ -26,10 +26,8 @@ namespace test { template struct input_iterator_adaptor { - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type - value_type; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer - pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::pointer pointer; typedef proxy reference; typedef std::ptrdiff_t difference_type; typedef std::input_iterator_tag iterator_category; @@ -66,14 +64,12 @@ namespace test { template struct copy_iterator_adaptor { - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type - value_type; - typedef BOOST_DEDUCED_TYPENAME - std::iterator_traits::difference_type difference_type; - typedef BOOST_DEDUCED_TYPENAME - std::iterator_traits::iterator_category iterator_category; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer - pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef + typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::iterator_category + iterator_category; + typedef typename std::iterator_traits::pointer pointer; typedef proxy reference; copy_iterator_adaptor() : base_() {} diff --git a/test/helpers/invariants.hpp b/test/helpers/invariants.hpp index 92012c84..a555da60 100644 --- a/test/helpers/invariants.hpp +++ b/test/helpers/invariants.hpp @@ -24,12 +24,12 @@ namespace test { template void check_equivalent_keys(X const& x1) { - BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq(); - typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; + typename X::key_equal eq = x1.key_eq(); + typedef typename X::key_type key_type; std::set > found_; - BOOST_DEDUCED_TYPENAME X::const_iterator it = x1.begin(), end = x1.end(); - BOOST_DEDUCED_TYPENAME X::size_type size = 0; + 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 @@ -60,9 +60,9 @@ namespace test { // Check that the keys are in the correct bucket and are // adjacent in the bucket. - BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key); - BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket), - lend = x1.end(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(*lit), key); ++lit) { @@ -106,12 +106,11 @@ namespace test { // Check that size in the buckets matches up. - BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0; + typename X::size_type bucket_size = 0; - for (BOOST_DEDUCED_TYPENAME X::size_type i = 0; i < x1.bucket_count(); - ++i) { - for (BOOST_DEDUCED_TYPENAME X::const_local_iterator begin2 = x1.begin(i), - end2 = x1.end(i); + 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; } diff --git a/test/helpers/metafunctions.hpp b/test/helpers/metafunctions.hpp index 0442920e..f5f13851 100644 --- a/test/helpers/metafunctions.hpp +++ b/test/helpers/metafunctions.hpp @@ -11,23 +11,19 @@ namespace test { template - struct is_set - : public boost::is_same + struct is_set : public boost::is_same { }; template struct has_unique_keys { - static char flip(BOOST_DEDUCED_TYPENAME Container::iterator const&); - static long flip( - std::pair const&); + static char flip(typename Container::iterator const&); + static long flip(std::pair const&); BOOST_STATIC_CONSTANT(bool, value = sizeof(long) == - sizeof( - flip(((Container*)0) - ->insert( - *(BOOST_DEDUCED_TYPENAME Container::value_type*)0)))); + sizeof(flip( + ((Container*)0)->insert(*(typename Container::value_type*)0)))); }; } diff --git a/test/helpers/random_values.hpp b/test/helpers/random_values.hpp index 912b8be0..d139d180 100644 --- a/test/helpers/random_values.hpp +++ b/test/helpers/random_values.hpp @@ -15,7 +15,7 @@ namespace test { template struct unordered_generator_set { - typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; + typedef typename X::value_type value_type; random_generator type_; @@ -41,8 +41,8 @@ namespace test { template struct unordered_generator_map { - typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; - typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type; + typedef typename X::key_type key_type; + typedef typename X::mapped_type mapped_type; random_generator type_; @@ -78,7 +78,7 @@ namespace test { template struct unordered_generator : public unordered_generator_base::type { - typedef BOOST_DEDUCED_TYPENAME unordered_generator_base::type base; + typedef typename unordered_generator_base::type base; unordered_generator(random_generator const& type = default_generator) : base(type) @@ -87,7 +87,7 @@ namespace test { }; template - struct random_values : public test::list + struct random_values : public test::list { random_values() {} diff --git a/test/helpers/strong.hpp b/test/helpers/strong.hpp index 040c18b4..3c936133 100644 --- a/test/helpers/strong.hpp +++ b/test/helpers/strong.hpp @@ -15,7 +15,7 @@ namespace test { template class strong { - typedef test::list values_type; + typedef test::list values_type; values_type values_; unsigned int allocations_; diff --git a/test/helpers/tracker.hpp b/test/helpers/tracker.hpp index f385cd8a..0f86ba6f 100644 --- a/test/helpers/tracker.hpp +++ b/test/helpers/tracker.hpp @@ -22,7 +22,7 @@ namespace test { template struct equals_to_compare { - typedef std::less type; + typedef std::less type; }; template <> struct equals_to_compare @@ -32,7 +32,7 @@ namespace test { template void compare_range(X1 const& x1, X2 const& x2) { - typedef test::list value_list; + typedef test::list value_list; value_list values1(x1.begin(), x1.end()); value_list values2(x2.begin(), x2.end()); values1.sort(); @@ -60,44 +60,38 @@ namespace test { template struct ordered_base { - typedef std::set::type> + typedef std::set::type> type; }; template struct ordered_base { - typedef std::multiset::type> + typedef std::multiset::type> type; }; template struct ordered_base { - typedef std::map::type> + typedef std::map::type> type; }; template struct ordered_base { - typedef std::multimap::type> + typedef std::multimap::type> type; }; template class ordered : public ordered_base::type { - typedef BOOST_DEDUCED_TYPENAME ordered_base::type base; + typedef typename ordered_base::type base; public: - typedef BOOST_DEDUCED_TYPENAME base::key_compare key_compare; + typedef typename base::key_compare key_compare; ordered() : base() {} @@ -105,12 +99,10 @@ namespace test { void compare(X const& x) { compare_range(x, *this); } - void compare_key( - X const& x, BOOST_DEDUCED_TYPENAME X::value_type const& val) + void compare_key(X const& x, typename X::value_type const& val) { compare_pairs(x.equal_range(get_key(val)), - this->equal_range(get_key(val)), - (BOOST_DEDUCED_TYPENAME X::value_type*)0); + this->equal_range(get_key(val)), (typename X::value_type*)0); } template void insert_range(It b, It e) @@ -123,10 +115,9 @@ namespace test { }; template - BOOST_DEDUCED_TYPENAME equals_to_compare::type create_compare( - Equals const&) + typename equals_to_compare::type create_compare(Equals const&) { - BOOST_DEDUCED_TYPENAME equals_to_compare::type x; + typename equals_to_compare::type x; return x; } diff --git a/test/unordered/assign_tests.cpp b/test/unordered/assign_tests.cpp index e3c2b9b3..f3d633b0 100644 --- a/test/unordered/assign_tests.cpp +++ b/test/unordered/assign_tests.cpp @@ -27,8 +27,8 @@ namespace assign_tests { template void assign_tests1(T*, test::random_generator generator) { - BOOST_DEDUCED_TYPENAME T::hasher hf; - BOOST_DEDUCED_TYPENAME T::key_equal eq; + typename T::hasher hf; + typename T::key_equal eq; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n"; { @@ -68,14 +68,14 @@ namespace assign_tests { template void assign_tests2(T*, test::random_generator generator) { - BOOST_DEDUCED_TYPENAME T::hasher hf1(1); - BOOST_DEDUCED_TYPENAME T::hasher hf2(2); - BOOST_DEDUCED_TYPENAME T::key_equal eq1(1); - BOOST_DEDUCED_TYPENAME T::key_equal eq2(2); - BOOST_DEDUCED_TYPENAME T::allocator_type al1(1); - BOOST_DEDUCED_TYPENAME T::allocator_type al2(2); + 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 BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; + typedef typename T::allocator_type allocator_type; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.0 - empty container\n"; { diff --git a/test/unordered/bucket_tests.cpp b/test/unordered/bucket_tests.cpp index 60a48887..c314d2c5 100644 --- a/test/unordered/bucket_tests.cpp +++ b/test/unordered/bucket_tests.cpp @@ -29,8 +29,8 @@ namespace bucket_tests { { test::check_instances check_; - typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; - typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; + typedef typename X::size_type size_type; + typedef typename X::const_local_iterator const_local_iterator; test::random_values v(1000, generator); X x(v.begin(), v.end()); @@ -41,9 +41,8 @@ namespace bucket_tests { << "<=" << x.max_bucket_count() << "\n"; } - for (BOOST_DEDUCED_TYPENAME test::random_values::const_iterator - it = v.begin(), - end = v.end(); + for (typename test::random_values::const_iterator it = v.begin(), + end = v.end(); it != end; ++it) { size_type bucket = x.bucket(test::get_key(*it)); diff --git a/test/unordered/compile_tests.hpp b/test/unordered/compile_tests.hpp index 691e4413..bb5256f8 100644 --- a/test/unordered/compile_tests.hpp +++ b/test/unordered/compile_tests.hpp @@ -52,27 +52,27 @@ template int implicit_construct() template void container_test(X& r, T const&) { - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; - typedef BOOST_DEDUCED_TYPENAME X::difference_type difference_type; - typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; + 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 BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type - iterator_value_type; - typedef BOOST_DEDUCED_TYPENAME - std::iterator_traits::value_type const_iterator_value_type; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type + typedef + typename std::iterator_traits::value_type iterator_value_type; + typedef typename std::iterator_traits::value_type + const_iterator_value_type; + typedef typename std::iterator_traits::difference_type iterator_difference_type; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_iterator>::difference_type const_iterator_difference_type; + typedef typename std::iterator_traits::difference_type + const_iterator_difference_type; - typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; - typedef BOOST_DEDUCED_TYPENAME X::reference reference; - typedef BOOST_DEDUCED_TYPENAME X::const_reference const_reference; + typedef typename X::value_type value_type; + typedef typename X::reference reference; + typedef typename X::const_reference const_reference; - typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; + typedef typename X::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; + typedef typename X::allocator_type allocator_type; // value_type @@ -97,8 +97,8 @@ template void container_test(X& r, T const&) // node_type - BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::value)); // difference_type @@ -208,9 +208,9 @@ template void container_test(X& r, T const&) template void unordered_destructible_test(X&) { - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; - typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; + typedef typename X::iterator iterator; + typedef typename X::const_iterator const_iterator; + typedef typename X::size_type size_type; X x1; @@ -247,31 +247,30 @@ template void unordered_destructible_test(X&) // Allocator - typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; + typedef typename X::allocator_type allocator_type; test::check_return_type::equals(a_const.get_allocator()); } template void unordered_set_test(X& r, Key const&) { - typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; - typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; + typedef typename X::value_type value_type; + typedef typename X::key_type key_type; BOOST_STATIC_ASSERT((boost::is_same::value)); // iterator pointer / const_pointer_type - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; - typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer - iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer + 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::pointer iterator_pointer; + typedef typename std::iterator_traits::pointer const_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer + typedef typename std::iterator_traits::pointer local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_local_iterator>::pointer const_local_iterator_pointer; + typedef typename std::iterator_traits::pointer + const_local_iterator_pointer; BOOST_STATIC_ASSERT( (boost::is_same::value)); @@ -285,52 +284,43 @@ template void unordered_set_test(X& r, Key const&) // pointer_traits BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + typename boost::pointer_traits::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT(( - boost::is_same::difference_type>::value)); + typename boost::pointer_traits::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); // pointer_traits - BOOST_STATIC_ASSERT(( - boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT(( - boost::is_same::difference_type>::value)); + typename boost::pointer_traits::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); // pointer_traits - BOOST_STATIC_ASSERT(( - boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT(( - boost::is_same::difference_type>::value)); + typename boost::pointer_traits::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); // pointer_traits BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + typename boost::pointer_traits::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + typename boost::pointer_traits::element_type>:: + value)); BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + typename boost::pointer_traits::difference_type>:: + value)); - typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME node_type::value_type node_value_type; + typedef typename X::node_type node_type; + typedef typename node_type::value_type node_value_type; BOOST_STATIC_ASSERT((boost::is_same::value)); // Call node_type functions. @@ -345,26 +335,25 @@ template void unordered_set_test(X& r, Key const&) template void unordered_map_test(X& r, Key const& k, T const& v) { - typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; - typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; + typedef typename X::value_type value_type; + typedef typename X::key_type key_type; BOOST_STATIC_ASSERT( (boost::is_same >::value)); // iterator pointer / const_pointer_type - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; - typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer - iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer + 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::pointer iterator_pointer; + typedef typename std::iterator_traits::pointer const_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer + typedef typename std::iterator_traits::pointer local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_local_iterator>::pointer const_local_iterator_pointer; + typedef typename std::iterator_traits::pointer + const_local_iterator_pointer; BOOST_STATIC_ASSERT((boost::is_same::value)); BOOST_STATIC_ASSERT( @@ -377,53 +366,44 @@ void unordered_map_test(X& r, Key const& k, T const& v) // pointer_traits BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); - BOOST_STATIC_ASSERT( - (boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT(( - boost::is_same::difference_type>::value)); + typename boost::pointer_traits::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); // pointer_traits - BOOST_STATIC_ASSERT(( - boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT(( - boost::is_same::difference_type>::value)); + typename boost::pointer_traits::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); // pointer_traits - BOOST_STATIC_ASSERT(( - boost::is_same::pointer>::value)); - BOOST_STATIC_ASSERT( - (boost::is_same::element_type>::value)); - BOOST_STATIC_ASSERT(( - boost::is_same::difference_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); // pointer_traits BOOST_STATIC_ASSERT((boost::is_same::pointer>::value)); + typename boost::pointer_traits::pointer>::value)); BOOST_STATIC_ASSERT((boost::is_same::element_type>::value)); + typename boost::pointer_traits::element_type>:: + value)); BOOST_STATIC_ASSERT((boost::is_same::difference_type>::value)); + typename boost::pointer_traits::difference_type>:: + value)); - typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME node_type::key_type node_key_type; - typedef BOOST_DEDUCED_TYPENAME node_type::mapped_type node_mapped_type; + 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::value)); BOOST_STATIC_ASSERT((boost::is_same::value)); @@ -495,12 +475,12 @@ template void equality_test(X& r) template void unordered_unique_test(X& r, T const& t) { - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; test::check_return_type >::equals(r.insert(t)); test::check_return_type >::equals(r.emplace(t)); - typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME X::insert_return_type insert_return_type; + typedef typename X::node_type node_type; + typedef typename X::insert_return_type insert_return_type; // insert_return_type @@ -527,7 +507,7 @@ template void unordered_unique_test(X& r, T const& t) template void unordered_equivalent_test(X& r, T const& t) { - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; test::check_return_type::equals(r.insert(t)); test::check_return_type::equals(r.emplace(t)); } @@ -535,8 +515,8 @@ template void unordered_equivalent_test(X& r, T const& t) template void unordered_map_functions(X&, Key const& k, T const& v) { - typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type; - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::mapped_type mapped_type; + typedef typename X::iterator iterator; X a; test::check_return_type::equals_ref(a[k]); @@ -567,52 +547,50 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq) { unordered_destructible_test(x); - typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; - typedef BOOST_DEDUCED_TYPENAME X::hasher hasher; - typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal; - typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; + 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 BOOST_DEDUCED_TYPENAME X::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; - typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; + 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 BOOST_DEDUCED_TYPENAME - std::iterator_traits::iterator_category iterator_category; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type + typedef typename std::iterator_traits::iterator_category + iterator_category; + typedef typename std::iterator_traits::difference_type iterator_difference; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer - iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::reference - iterator_reference; + typedef typename std::iterator_traits::pointer iterator_pointer; + typedef typename std::iterator_traits::reference iterator_reference; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - local_iterator>::iterator_category local_iterator_category; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - local_iterator>::difference_type local_iterator_difference; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer + typedef typename std::iterator_traits::iterator_category + local_iterator_category; + typedef typename std::iterator_traits::difference_type + local_iterator_difference; + typedef typename std::iterator_traits::pointer local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::reference + typedef typename std::iterator_traits::reference local_iterator_reference; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_iterator>::iterator_category const_iterator_category; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_iterator>::difference_type const_iterator_difference; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::pointer + typedef typename std::iterator_traits::iterator_category + const_iterator_category; + typedef typename std::iterator_traits::difference_type + const_iterator_difference; + typedef typename std::iterator_traits::pointer const_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::reference + typedef typename std::iterator_traits::reference const_iterator_reference; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_local_iterator>::iterator_category const_local_iterator_category; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_local_iterator>::difference_type const_local_iterator_difference; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_local_iterator>::pointer const_local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME std::iterator_traits< - const_local_iterator>::reference const_local_iterator_reference; - typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; + typedef typename std::iterator_traits::iterator_category + const_local_iterator_category; + typedef typename std::iterator_traits::difference_type + const_local_iterator_difference; + typedef typename std::iterator_traits::pointer + const_local_iterator_pointer; + typedef typename std::iterator_traits::reference + const_local_iterator_reference; + typedef typename X::allocator_type allocator_type; BOOST_STATIC_ASSERT((boost::is_same::value)); // boost::function_requires >(); @@ -731,15 +709,15 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq) { unordered_test(x, k, hf, eq); - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; - typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; + 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(); - BOOST_DEDUCED_TYPENAME X::value_type* i = 0; - BOOST_DEDUCED_TYPENAME X::value_type* j = 0; + typename X::value_type* i = 0; + typename X::value_type* j = 0; // Constructors @@ -829,8 +807,8 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq) sink(a7a); sink(a9a); - typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; + 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::equals(n_const.get_allocator()); } @@ -840,9 +818,9 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq) { unordered_test(x, k, hf, eq); - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; - typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; + 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()); diff --git a/test/unordered/constructor_tests.cpp b/test/unordered/constructor_tests.cpp index 8e615f90..5f571986 100644 --- a/test/unordered/constructor_tests.cpp +++ b/test/unordered/constructor_tests.cpp @@ -25,9 +25,9 @@ namespace constructor_tests { template void constructor_tests1(T*, test::random_generator generator) { - BOOST_DEDUCED_TYPENAME T::hasher hf; - BOOST_DEDUCED_TYPENAME T::key_equal eq; - BOOST_DEDUCED_TYPENAME T::allocator_type al; + typename T::hasher hf; + typename T::key_equal eq; + typename T::allocator_type al; UNORDERED_SUB_TEST("Construct 1") { @@ -176,15 +176,15 @@ namespace constructor_tests { template void constructor_tests2(T*, test::random_generator const& generator) { - BOOST_DEDUCED_TYPENAME T::hasher hf; - BOOST_DEDUCED_TYPENAME T::hasher hf1(1); - BOOST_DEDUCED_TYPENAME T::hasher hf2(2); - BOOST_DEDUCED_TYPENAME T::key_equal eq; - BOOST_DEDUCED_TYPENAME T::key_equal eq1(1); - BOOST_DEDUCED_TYPENAME T::key_equal eq2(2); - BOOST_DEDUCED_TYPENAME T::allocator_type al; - BOOST_DEDUCED_TYPENAME T::allocator_type al1(1); - BOOST_DEDUCED_TYPENAME T::allocator_type al2(2); + 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") { @@ -274,14 +274,11 @@ namespace constructor_tests { { test::check_instances check_; test::random_values v(100, generator); - BOOST_DEDUCED_TYPENAME test::random_values::const_iterator v_begin = - v.begin(), - v_end = - v.end(); + typename test::random_values::const_iterator v_begin = v.begin(), + v_end = v.end(); T x(test::input_iterator(v_begin), test::input_iterator(v_end), 0, hf1, eq1); - BOOST_DEDUCED_TYPENAME T::const_iterator x_begin = x.begin(), - x_end = x.end(); + 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); @@ -320,7 +317,7 @@ namespace constructor_tests { } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - std::initializer_list list; + std::initializer_list list; UNORDERED_SUB_TEST("Initializer list construct 1") { @@ -386,8 +383,8 @@ namespace constructor_tests { template void map_constructor_test(T*, test::random_generator const& generator) { - typedef test::list > + typedef test::list< + std::pair > list; test::random_values v(1000, generator); list l(v.begin(), v.end()); diff --git a/test/unordered/copy_tests.cpp b/test/unordered/copy_tests.cpp index 17df86d8..1f1ac8f5 100644 --- a/test/unordered/copy_tests.cpp +++ b/test/unordered/copy_tests.cpp @@ -25,11 +25,11 @@ namespace copy_tests { template void copy_construct_tests1(T*, test::random_generator const& generator) { - typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; + typedef typename T::allocator_type allocator_type; - BOOST_DEDUCED_TYPENAME T::hasher hf; - BOOST_DEDUCED_TYPENAME T::key_equal eq; - BOOST_DEDUCED_TYPENAME T::allocator_type al; + typename T::hasher hf; + typename T::key_equal eq; + typename T::allocator_type al; { test::check_instances check_; @@ -84,12 +84,12 @@ namespace copy_tests { template void copy_construct_tests2(T*, test::random_generator const& generator) { - BOOST_DEDUCED_TYPENAME T::hasher hf(1); - BOOST_DEDUCED_TYPENAME T::key_equal eq(1); - BOOST_DEDUCED_TYPENAME T::allocator_type al(1); - BOOST_DEDUCED_TYPENAME T::allocator_type al2(2); + typename T::hasher hf(1); + typename T::key_equal eq(1); + typename T::allocator_type al(1); + typename T::allocator_type al2(2); - typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; + typedef typename T::allocator_type allocator_type; { test::check_instances check_; diff --git a/test/unordered/erase_tests.cpp b/test/unordered/erase_tests.cpp index ec26ab2d..fecb7dc0 100644 --- a/test/unordered/erase_tests.cpp +++ b/test/unordered/erase_tests.cpp @@ -27,8 +27,8 @@ namespace erase_tests { template void erase_tests1(Container*, test::random_generator generator) { - typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME Container::const_iterator c_iterator; + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator c_iterator; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n"; { @@ -37,8 +37,7 @@ namespace erase_tests { test::random_values v(1000, generator); Container x(v.begin(), v.end()); int iterations = 0; - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { std::size_t count = x.count(test::get_key(*it)); std::size_t old_size = x.size(); @@ -60,8 +59,7 @@ namespace erase_tests { std::size_t size = x.size(); int iterations = 0; while (size > 0 && !x.empty()) { - BOOST_DEDUCED_TYPENAME Container::key_type key = - test::get_key(*x.begin()); + typename Container::key_type key = test::get_key(*x.begin()); std::size_t count = x.count(key); iterator pos = x.erase(x.begin()); --size; @@ -92,8 +90,7 @@ namespace erase_tests { pos = test::next(prev); } next = test::next(pos); - BOOST_DEDUCED_TYPENAME Container::key_type key = - test::get_key(*pos); + typename Container::key_type key = test::get_key(*pos); std::size_t count = x.count(key); BOOST_TEST(count > 0); BOOST_TEST(next == x.erase(pos)); @@ -163,7 +160,7 @@ namespace erase_tests { test::next(iterators.begin(), start + length)); BOOST_TEST(x.size() == iterators.size() - 1); - BOOST_DEDUCED_TYPENAME std::vector::const_iterator i2 = + typename std::vector::const_iterator i2 = iterators.begin(); for (c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) { BOOST_TEST(i1 == *i2); @@ -186,8 +183,7 @@ namespace erase_tests { std::size_t size = x.size(); int iterations = 0; while (size > 0 && !x.empty()) { - BOOST_DEDUCED_TYPENAME Container::key_type key = - test::get_key(*x.begin()); + typename Container::key_type key = test::get_key(*x.begin()); std::size_t count = x.count(key); x.quick_erase(x.begin()); --size; @@ -209,7 +205,7 @@ namespace erase_tests { int iterations = 0; while (size > 0 && !x.empty()) { std::size_t index = test::random_value(x.size()); - BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next; + typename Container::const_iterator prev, pos, next; if (index == 0) { prev = pos = x.begin(); } else { @@ -217,8 +213,7 @@ namespace erase_tests { pos = test::next(prev); } next = test::next(pos); - BOOST_DEDUCED_TYPENAME Container::key_type key = - test::get_key(*pos); + typename Container::key_type key = test::get_key(*pos); std::size_t count = x.count(key); BOOST_TEST(count > 0); x.quick_erase(pos); diff --git a/test/unordered/extract_tests.cpp b/test/unordered/extract_tests.cpp index aef7fb4e..14338738 100644 --- a/test/unordered/extract_tests.cpp +++ b/test/unordered/extract_tests.cpp @@ -32,8 +32,7 @@ namespace extract_tests { test::random_values v(1000, generator); Container x(v.begin(), v.end()); int iterations = 0; - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { std::size_t count = x.count(test::get_key(*it)); std::size_t old_size = x.size(); @@ -64,8 +63,7 @@ namespace extract_tests { std::size_t size = x.size(); int iterations = 0; while (size > 0 && !x.empty()) { - BOOST_DEDUCED_TYPENAME Container::key_type key = - test::get_key(*x.begin()); + typename Container::key_type key = test::get_key(*x.begin()); std::size_t count = x.count(key); typename Container::node_type n = x.extract(x.begin()); BOOST_TEST(n); @@ -89,7 +87,7 @@ namespace extract_tests { while (size > 0 && !x.empty()) { using namespace std; int index = rand() % (int)x.size(); - BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next; + typename Container::const_iterator prev, pos, next; if (index == 0) { prev = pos = x.begin(); } else { @@ -97,8 +95,7 @@ namespace extract_tests { pos = test::next(prev); } next = test::next(pos); - BOOST_DEDUCED_TYPENAME Container::key_type key = - test::get_key(*pos); + typename Container::key_type key = test::get_key(*pos); std::size_t count = x.count(key); typename Container::node_type n = x.extract(pos); BOOST_TEST(n); diff --git a/test/unordered/find_tests.cpp b/test/unordered/find_tests.cpp index 268d42bb..031371c3 100644 --- a/test/unordered/find_tests.cpp +++ b/test/unordered/find_tests.cpp @@ -22,7 +22,7 @@ namespace find_tests { template void find_tests1(X*, test::random_generator generator) { - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; { test::check_instances check_; @@ -33,11 +33,10 @@ namespace find_tests { test::ordered tracker = test::create_ordered(x); tracker.insert_range(v.begin(), v.end()); - for (BOOST_DEDUCED_TYPENAME test::ordered::const_iterator it1 = - tracker.begin(); + for (typename test::ordered::const_iterator it1 = tracker.begin(); it1 != tracker.end(); ++it1) { - BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key(*it1); - BOOST_DEDUCED_TYPENAME X::const_iterator const_pos = x_const.find(key); + typename X::key_type key = test::get_key(*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() && @@ -48,16 +47,15 @@ namespace find_tests { BOOST_TEST(x.count(key) == tracker.count(key)); test::compare_pairs(x.equal_range(key), tracker.equal_range(key), - (BOOST_DEDUCED_TYPENAME X::value_type*)0); + (typename X::value_type*)0); test::compare_pairs(x_const.equal_range(key), tracker.equal_range(key), - (BOOST_DEDUCED_TYPENAME X::value_type*)0); + (typename X::value_type*)0); } test::random_values v2(500, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::const_iterator it2 = - v2.begin(); + for (typename test::random_values::const_iterator it2 = v2.begin(); it2 != v2.end(); ++it2) { - BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key(*it2); + typename X::key_type key = test::get_key(*it2); if (tracker.find(test::get_key(key)) == tracker.end()) { BOOST_TEST(x.find(key) == x.end()); BOOST_TEST(x_const.find(key) == x_const.end()); @@ -74,10 +72,9 @@ namespace find_tests { X x; test::random_values v2(5, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::const_iterator it3 = - v2.begin(); + for (typename test::random_values::const_iterator it3 = v2.begin(); it3 != v2.end(); ++it3) { - BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key(*it3); + typename X::key_type key = test::get_key(*it3); BOOST_TEST(x.find(key) == x.end()); BOOST_TEST(x.count(key) == 0); std::pair range = x.equal_range(key); @@ -116,8 +113,7 @@ namespace find_tests { template void find_compatible_keys_test(X*, test::random_generator generator) { - typedef BOOST_DEDUCED_TYPENAME test::random_values::iterator - value_iterator; + typedef typename test::random_values::iterator value_iterator; test::random_values v(500, generator); X x(v.begin(), v.end()); @@ -125,14 +121,14 @@ namespace find_tests { compatible_predicate eq; for (value_iterator it = v.begin(), end = v.end(); it != end; ++it) { - BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key(*it); + typename X::key_type key = test::get_key(*it); BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq)); } test::random_values v2(20, generator); for (value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) { - BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key(*it); + typename X::key_type key = test::get_key(*it); BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq)); } } diff --git a/test/unordered/insert_tests.cpp b/test/unordered/insert_tests.cpp index db3bae82..7ddb41fd 100644 --- a/test/unordered/insert_tests.cpp +++ b/test/unordered/insert_tests.cpp @@ -30,7 +30,7 @@ namespace insert_tests { { test::check_instances check_; - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; typedef test::ordered ordered; UNORDERED_SUB_TEST("insert(value) tests for containers with unique keys") @@ -40,16 +40,14 @@ namespace insert_tests { test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); std::pair r1 = x.insert(*it); - std::pair r2 = - tracker.insert(*it); + std::pair r2 = tracker.insert(*it); BOOST_TEST(r1.second == r2.second); BOOST_TEST(*r1.first == *r2.first); @@ -71,17 +69,15 @@ namespace insert_tests { test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); typename X::value_type value = *it; std::pair r1 = x.insert(boost::move(value)); - std::pair r2 = - tracker.insert(*it); + std::pair r2 = tracker.insert(*it); BOOST_TEST(r1.second == r2.second); BOOST_TEST(*r1.first == *r2.first); @@ -109,15 +105,13 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); - BOOST_DEDUCED_TYPENAME X::iterator r1 = x.insert(*it); - BOOST_DEDUCED_TYPENAME test::ordered::iterator r2 = - tracker.insert(*it); + typename X::iterator r1 = x.insert(*it); + typename test::ordered::iterator r2 = tracker.insert(*it); BOOST_TEST(*r1 == *r2); @@ -138,16 +132,14 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); typename X::value_type value = *it; - BOOST_DEDUCED_TYPENAME X::iterator r1 = x.insert(boost::move(value)); - BOOST_DEDUCED_TYPENAME test::ordered::iterator r2 = - tracker.insert(*it); + typename X::iterator r1 = x.insert(boost::move(value)); + typename test::ordered::iterator r2 = tracker.insert(*it); BOOST_TEST(*r1 == *r2); @@ -164,10 +156,10 @@ namespace insert_tests { template void insert_tests2(X*, test::random_generator generator) { - typedef BOOST_DEDUCED_TYPENAME test::ordered tracker_type; - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; - typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; - typedef BOOST_DEDUCED_TYPENAME tracker_type::iterator tracker_iterator; + typedef typename test::ordered 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") { @@ -177,10 +169,9 @@ namespace insert_tests { tracker_type tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); iterator r1 = x.insert(x.begin(), *it); @@ -206,10 +197,9 @@ namespace insert_tests { tracker_type tracker = test::create_ordered(x); test::random_values v(100, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + 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); @@ -235,10 +225,9 @@ namespace insert_tests { tracker_type tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); pos = x.insert(pos, *it); @@ -264,10 +253,9 @@ namespace insert_tests { tracker_type tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); typename X::value_type value = *it; @@ -293,10 +281,9 @@ namespace insert_tests { tracker_type tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); x.insert(it, test::next(it)); @@ -349,10 +336,8 @@ namespace insert_tests { X x; test::random_values v(1000, generator); - BOOST_DEDUCED_TYPENAME test::random_values::const_iterator begin = - v.begin(), - end = - v.end(); + typename test::random_values::const_iterator begin = v.begin(), + end = v.end(); x.insert(test::input_iterator(begin), test::input_iterator(end)); test::check_container(x, v); @@ -394,14 +379,12 @@ namespace insert_tests { test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end();) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = - x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); - BOOST_DEDUCED_TYPENAME test::random_values::iterator next = it; + typename test::random_values::iterator next = it; for (std::size_t j = test::random_value(20); j > 0; ++j) { ++next; if (next == v.end()) { @@ -428,7 +411,7 @@ namespace insert_tests { template void unique_emplace_tests1(X*, test::random_generator generator) { - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; typedef test::ordered ordered; X x; @@ -436,15 +419,14 @@ namespace insert_tests { test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); std::pair r1 = x.emplace(*it); - std::pair r2 = - tracker.insert(*it); + std::pair r2 = tracker.insert(*it); BOOST_TEST(r1.second == r2.second); BOOST_TEST(*r1.first == *r2.first); @@ -467,14 +449,13 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); - BOOST_DEDUCED_TYPENAME X::iterator r1 = x.emplace(*it); - BOOST_DEDUCED_TYPENAME test::ordered::iterator r2 = - tracker.insert(*it); + typename X::iterator r1 = x.emplace(*it); + typename test::ordered::iterator r2 = tracker.insert(*it); BOOST_TEST(*r1 == *r2); @@ -497,10 +478,10 @@ namespace insert_tests { test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); typename X::value_type value = *it; @@ -558,9 +539,9 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); x[it->first] = it->second; @@ -579,7 +560,7 @@ namespace insert_tests { template void map_tests2(X*, test::random_generator generator) { - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; UNORDERED_SUB_TEST("insert_or_assign") { @@ -589,10 +570,9 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); std::pair r = x.insert_or_assign(it->first, it->second); @@ -618,10 +598,9 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + 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); @@ -647,10 +626,9 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + 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); @@ -677,10 +655,9 @@ namespace insert_tests { iterator last = x.begin(); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + 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); @@ -704,7 +681,7 @@ namespace insert_tests { template void try_emplace_tests(X*, test::random_generator generator) { - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; UNORDERED_SUB_TEST("try_emplace(key, value)") { @@ -714,10 +691,9 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); iterator pos = x.find(it->first); @@ -745,7 +721,7 @@ namespace insert_tests { test::check_equivalent_keys(x); } - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; UNORDERED_SUB_TEST("try_emplace(begin(), key, value)") { @@ -755,10 +731,9 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); iterator pos = x.find(it->first); @@ -783,7 +758,7 @@ namespace insert_tests { test::check_equivalent_keys(x); } - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; UNORDERED_SUB_TEST("try_emplace(end(), key, value)") { @@ -793,10 +768,9 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); iterator pos = x.find(it->first); @@ -820,7 +794,7 @@ namespace insert_tests { test::check_equivalent_keys(x); } - typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef typename X::iterator iterator; UNORDERED_SUB_TEST("try_emplace(pos, key, value)") { @@ -830,10 +804,9 @@ namespace insert_tests { test::ordered tracker = test::create_ordered(x); test::random_values v(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::iterator it = - v.begin(); + for (typename test::random_values::iterator it = v.begin(); it != v.end(); ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + typename X::size_type old_bucket_count = x.bucket_count(); float b = x.max_load_factor(); iterator pos = x.find(it->first); @@ -866,8 +839,8 @@ namespace insert_tests { { test::check_instances check_; - typedef test::list > + typedef test::list< + std::pair > list; test::random_values v(1000, generator); list l(v.begin(), v.end()); @@ -883,11 +856,11 @@ namespace insert_tests { { test::check_instances check_; - typedef test::list > + typedef test::list< + std::pair > list; - test::random_values > + test::random_values< + boost::unordered_map > v(1000, generator); list l(v.begin(), v.end()); diff --git a/test/unordered/load_factor_tests.cpp b/test/unordered/load_factor_tests.cpp index 9c76a743..9006c1bd 100644 --- a/test/unordered/load_factor_tests.cpp +++ b/test/unordered/load_factor_tests.cpp @@ -47,12 +47,11 @@ namespace load_factor_tests { test::random_values values(1000, generator); - for (BOOST_DEDUCED_TYPENAME test::random_values::const_iterator - it = values.begin(), - end = values.end(); + for (typename test::random_values::const_iterator it = values.begin(), + end = values.end(); it != end; ++it) { - BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(), - old_bucket_count = x.bucket_count(); + typename X::size_type old_size = x.size(), + old_bucket_count = x.bucket_count(); x.insert(*it); if (static_cast(old_size + 1) <= b * static_cast(old_bucket_count)) diff --git a/test/unordered/move_tests.cpp b/test/unordered/move_tests.cpp index 5d0d37d8..82ba6011 100644 --- a/test/unordered/move_tests.cpp +++ b/test/unordered/move_tests.cpp @@ -43,8 +43,8 @@ namespace move_tests { template T create(test::random_values const& v, test::object_count& count, - BOOST_DEDUCED_TYPENAME T::hasher hf, BOOST_DEDUCED_TYPENAME T::key_equal eq, - BOOST_DEDUCED_TYPENAME T::allocator_type al, float mlf) + 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); @@ -56,9 +56,9 @@ namespace move_tests { template void move_construct_tests1(T* ptr, test::random_generator const& generator) { - BOOST_DEDUCED_TYPENAME T::hasher hf; - BOOST_DEDUCED_TYPENAME T::key_equal eq; - BOOST_DEDUCED_TYPENAME T::allocator_type al; + typename T::hasher hf; + typename T::key_equal eq; + typename T::allocator_type al; { test::check_instances check_; @@ -107,10 +107,10 @@ namespace move_tests { template void move_construct_tests2(T*, test::random_generator const& generator) { - BOOST_DEDUCED_TYPENAME T::hasher hf(1); - BOOST_DEDUCED_TYPENAME T::key_equal eq(1); - BOOST_DEDUCED_TYPENAME T::allocator_type al(1); - BOOST_DEDUCED_TYPENAME T::allocator_type al2(2); + 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; @@ -180,11 +180,11 @@ namespace move_tests { template void move_assign_tests2(T*, test::random_generator const& generator) { - BOOST_DEDUCED_TYPENAME T::hasher hf(1); - BOOST_DEDUCED_TYPENAME T::key_equal eq(1); - BOOST_DEDUCED_TYPENAME T::allocator_type al1(1); - BOOST_DEDUCED_TYPENAME T::allocator_type al2(2); - typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; + 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 v(500, generator); diff --git a/test/unordered/node_handle_tests.cpp b/test/unordered/node_handle_tests.cpp index f1b9c965..2d5b1eab 100644 --- a/test/unordered/node_handle_tests.cpp +++ b/test/unordered/node_handle_tests.cpp @@ -147,24 +147,24 @@ UNORDERED_AUTO_TEST (failed_insertion_with_hint) { template bool node_handle_compare( - NodeHandle const& nh, BOOST_DEDUCED_TYPENAME NodeHandle::value_type const& x) + NodeHandle const& nh, typename NodeHandle::value_type const& x) { return x == nh.value(); } template -bool node_handle_compare(NodeHandle const& nh, - std::pair const& x) +bool node_handle_compare( + NodeHandle const& nh, std::pair const& x) { return x.first == nh.key() && x.second == nh.mapped(); } template void node_handle_tests_impl(Container& c) { - typedef BOOST_DEDUCED_TYPENAME Container::node_type node_type; + typedef typename Container::node_type node_type; - BOOST_DEDUCED_TYPENAME Container::value_type value = *c.begin(); + typename Container::value_type value = *c.begin(); node_type n1; BOOST_TEST(!n1); @@ -195,9 +195,9 @@ template void node_handle_tests_impl(Container& c) n3 = boost::move(n3); BOOST_TEST(!n3); - BOOST_DEDUCED_TYPENAME Container::value_type value1 = *c.begin(); + typename Container::value_type value1 = *c.begin(); n1 = c.extract(c.begin()); - BOOST_DEDUCED_TYPENAME Container::value_type value2 = *c.begin(); + typename Container::value_type value2 = *c.begin(); n2 = c.extract(c.begin()); n3 = node_type(); @@ -248,15 +248,13 @@ UNORDERED_AUTO_TEST (node_handle_tests) { template void insert_node_handle_unique(Container1& c1, Container2& c2) { - typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; - BOOST_STATIC_ASSERT((boost::is_same::value)); + typedef typename Container1::node_type node_type; + typedef typename Container1::value_type value_type; + BOOST_STATIC_ASSERT( + (boost::is_same::value)); - typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type - insert_return_type1; - typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type - insert_return_type2; + 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()); @@ -293,15 +291,14 @@ void insert_node_handle_unique(Container1& c1, Container2& c2) template void insert_node_handle_unique2(Container1& c1, Container2& c2) { - typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; - BOOST_STATIC_ASSERT((boost::is_same::value)); + typedef typename Container1::node_type node_type; + typedef typename Container1::value_type value_type; + BOOST_STATIC_ASSERT( + (boost::is_same::value)); - // typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type + // typedef typename Container1::insert_return_type // insert_return_type1; - typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type - insert_return_type2; + typedef typename Container2::insert_return_type insert_return_type2; while (!c1.empty()) { value_type v = *c1.begin(); @@ -327,13 +324,13 @@ void insert_node_handle_unique2(Container1& c1, Container2& c2) template void insert_node_handle_equiv(Container1& c1, Container2& c2) { - typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; - BOOST_STATIC_ASSERT((boost::is_same::value)); + typedef typename Container1::node_type node_type; + typedef typename Container1::value_type value_type; + BOOST_STATIC_ASSERT( + (boost::is_same::value)); - typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1; - typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2; + typedef typename Container1::iterator iterator1; + typedef typename Container2::iterator iterator2; iterator1 r1 = c1.insert(node_type()); iterator2 r2 = c2.insert(node_type()); diff --git a/test/unordered/rehash_tests.cpp b/test/unordered/rehash_tests.cpp index 87a49593..65c08936 100644 --- a/test/unordered/rehash_tests.cpp +++ b/test/unordered/rehash_tests.cpp @@ -20,8 +20,7 @@ namespace rehash_tests { test::seed_t initialize_seed(2974); - template - bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n) + template bool postcondition(X const& x, typename X::size_type n) { return static_cast(x.bucket_count()) >= static_cast(x.size()) / x.max_load_factor() && diff --git a/test/unordered/simple_tests.cpp b/test/unordered/simple_tests.cpp index 9fa21e17..d8a9ce41 100644 --- a/test/unordered/simple_tests.cpp +++ b/test/unordered/simple_tests.cpp @@ -73,7 +73,7 @@ template void simple_test(X const& a) } { - BOOST_TEST(a.size() == static_cast( + BOOST_TEST(a.size() == static_cast( std::distance(a.begin(), a.end()))); } diff --git a/test/unordered/swap_tests.cpp b/test/unordered/swap_tests.cpp index 52d2c875..9a7106ef 100644 --- a/test/unordered/swap_tests.cpp +++ b/test/unordered/swap_tests.cpp @@ -78,9 +78,9 @@ namespace swap_tests { { swap_tests1(ptr, generator); - typedef BOOST_DEDUCED_TYPENAME X::hasher hasher; - typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal; - typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; + typedef typename X::hasher hasher; + typedef typename X::key_equal key_equal; + typedef typename X::allocator_type allocator_type; { test::check_instances check_; diff --git a/test/unordered/unnecessary_copy_tests.cpp b/test/unordered/unnecessary_copy_tests.cpp index 929d55fe..1c5ff4b7 100644 --- a/test/unordered/unnecessary_copy_tests.cpp +++ b/test/unordered/unnecessary_copy_tests.cpp @@ -177,7 +177,7 @@ namespace unnecessary_copy_tests { template void unnecessary_copy_insert_test(T*) { T x; - BOOST_DEDUCED_TYPENAME T::value_type a; + typename T::value_type a; reset(); x.insert(a); COPY_COUNT(1); @@ -187,13 +187,13 @@ namespace unnecessary_copy_tests { template void unnecessary_copy_insert_rvalue_set_test(T*) { T x; - BOOST_DEDUCED_TYPENAME T::value_type a; + typename T::value_type a; reset(); x.insert(boost::move(a)); COPY_COUNT(0); MOVE_COUNT(1); - BOOST_DEDUCED_TYPENAME T::value_type a2; + typename T::value_type a2; reset(); x.insert(boost::move(a)); COPY_COUNT(0); @@ -207,7 +207,7 @@ namespace unnecessary_copy_tests { // construct_from_args. T x; - BOOST_DEDUCED_TYPENAME T::value_type a; + typename T::value_type a; reset(); x.insert(boost::move(a)); #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -218,7 +218,7 @@ namespace unnecessary_copy_tests { MOVE_COUNT(1); #endif - BOOST_DEDUCED_TYPENAME T::value_type a2; + typename T::value_type a2; reset(); x.insert(boost::move(a)); #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -243,7 +243,7 @@ namespace unnecessary_copy_tests { { reset(); T x; - BOOST_DEDUCED_TYPENAME T::value_type a; + typename T::value_type a; COPY_COUNT(1); x.emplace(a); COPY_COUNT(2); @@ -253,7 +253,7 @@ namespace unnecessary_copy_tests { { reset(); T x; - x.emplace(source()); + x.emplace(source()); #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) COPY_COUNT(1); #else @@ -271,7 +271,7 @@ namespace unnecessary_copy_tests { { reset(); T x; - BOOST_DEDUCED_TYPENAME T::value_type a; + typename T::value_type a; COPY_COUNT(1); MOVE_COUNT(0); x.emplace(std::move(a)); @@ -287,7 +287,7 @@ namespace unnecessary_copy_tests { { reset(); T x; - BOOST_DEDUCED_TYPENAME T::value_type a; + typename T::value_type a; COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1); x.emplace(boost::move(a)); @@ -308,7 +308,7 @@ namespace unnecessary_copy_tests { { reset(); T x; - BOOST_DEDUCED_TYPENAME T::value_type a; + typename T::value_type a; COPY_COUNT(1); MOVE_COUNT(0); x.emplace(boost::move(a)); @@ -325,7 +325,7 @@ namespace unnecessary_copy_tests { T x; COPY_COUNT(0); MOVE_COUNT(0); - BOOST_DEDUCED_TYPENAME T::value_type a; + typename T::value_type a; COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1); x.emplace(boost::move(a)); From 6491f6c10aadf0e0197d3c9df6a6dcd824791f7e Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 2 Feb 2018 23:37:36 +0000 Subject: [PATCH 49/50] Python script to download the latest snapshot for CI testing --- .appveyor.yml | 7 ++-- .travis.yml | 16 +------- build/download-boost-snapshot.py | 66 ++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 build/download-boost-snapshot.py diff --git a/.appveyor.yml b/.appveyor.yml index eed13281..ba7290e9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,10 +16,9 @@ environment: TOOLSET: msvc-14.1 install: - - cd c:\projects - - curl -sSL -o boost.7z https://dl.bintray.com/boostorg/master/boost_1_67_0-snapshot.7z - - 7z x boost.7z - - set BOOST_ROOT=c:\projects\boost_1_67_0 + - set BOOST_ROOT=c:\projects\boost + - cd c:\projects\ + - python %APPVEYOR_BUILD_FOLDER%\build\download-boost-snapshot.py master - rd /s /q %BOOST_ROOT%\boost\unordered - cd %BOOST_ROOT%\tools\build - cmd /c bootstrap diff --git a/.travis.yml b/.travis.yml index 554bb82e..f4400893 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,25 +66,11 @@ before_script: snapshot=master fi - # Set download_url for snapshot - if [ $snapshot == "stable" ] - then - download_url=https://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/${BOOST_FILENAME}.tar.bz2/download - else - download_url=$(curl https://api.bintray.com/packages/boostorg/$snapshot/snapshot/files | - python -c "import os.path, sys, json; x = json.load(sys.stdin); print '\n'.join(a['path'] for a in x if os.path.splitext(a['path'])[1] == '.bz2')" | - head -n 1 | - sed "s/^/http:\/\/dl.bintray.com\/boostorg\/$snapshot\//") - fi - # Download and extract snapshot echo "Downloading ${download_url}" mkdir $HOME/download - mkdir $HOME/extract cd $HOME/download - wget -O boost.tar.bz2 $download_url - cd $HOME/extract - tar -xjf $HOME/download/boost.tar.bz2 + python ${TRAVIS_BUILD_DIR}/build/download-boost-snapshot.py $snapshot mv * ${BOOST_ROOT} - rm -r ${BOOST_ROOT}/boost/unordered - cd ${BOOST_ROOT}/tools/build diff --git a/build/download-boost-snapshot.py b/build/download-boost-snapshot.py new file mode 100644 index 00000000..a9d8ba98 --- /dev/null +++ b/build/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]) From 8207ebe3814d05ca32a788de376342ab4d741c5c Mon Sep 17 00:00:00 2001 From: Daniel James Date: Fri, 9 Feb 2018 09:00:45 +0000 Subject: [PATCH 50/50] Use bash to run bootstrap.sh When using a zipfile it isn't marked as executable. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f4400893..cc1829f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,7 +75,7 @@ before_script: - rm -r ${BOOST_ROOT}/boost/unordered - cd ${BOOST_ROOT}/tools/build - mkdir ${HOME}/opt - - ./bootstrap.sh + - bash bootstrap.sh - ./b2 install --prefix=$HOME/opt after_success: