diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000..ba7290e9 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,32 @@ +# 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: + - 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 + - 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% diff --git a/.travis.yml b/.travis.yml index 14c0168a..cc1829f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,6 @@ language: c++ addons: apt: packages: - - libboost-tools-dev - libxml2-utils - g++-multilib @@ -19,46 +18,70 @@ 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++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: | 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 before_script: + - 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 - 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 + snapshot=master + fi + + # Download and extract snapshot + echo "Downloading ${download_url}" + mkdir $HOME/download + cd $HOME/download + python ${TRAVIS_BUILD_DIR}/build/download-boost-snapshot.py $snapshot + mv * ${BOOST_ROOT} + - rm -r ${BOOST_ROOT}/boost/unordered + - cd ${BOOST_ROOT}/tools/build + - mkdir ${HOME}/opt + - bash 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 -q include=${HOME}/boost 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 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]) 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/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 d25026fe..9914683f 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -13,12 +13,11 @@ #endif #include -#include +#include +#include #include -#include #include #include -#include #include #include #include @@ -33,11 +32,13 @@ #include #include #include +#include +#include #include -#include #include #include #include +#include #include #include #include @@ -195,6 +196,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 { @@ -244,9 +257,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> { }; @@ -541,21 +553,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); - } - }; } } } @@ -741,6 +738,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); } + }; } } } @@ -855,6 +964,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 @@ -934,72 +1115,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 { @@ -1014,6 +1129,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) @@ -1310,6 +1426,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; }; } } @@ -1330,9 +1449,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 @@ -1844,7 +1974,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_address(node_)); node_allocator_traits::deallocate(alloc_, node_, 1); } } @@ -1853,7 +1983,7 @@ namespace boost { { BOOST_ASSERT(!node_); node_ = node_allocator_traits::allocate(alloc_, 1); - new (pointer::get(node_)) node(); + new ((void*)boost::to_address(node_)) node(); } template struct node_tmp @@ -1884,7 +2014,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_address(node_)); node_allocator_traits::deallocate(alloc_, node_, 1); } } @@ -2088,11 +2218,7 @@ namespace boost { // // all no throw - template - struct l_iterator - : public std::iterator + template struct l_iterator { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template @@ -2106,7 +2232,12 @@ 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; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; l_iterator() BOOST_NOEXCEPT : ptr_() {} @@ -2147,11 +2278,7 @@ namespace boost { } }; - template - struct cl_iterator - : public std::iterator + template struct cl_iterator { friend struct boost::unordered::iterator_detail::l_iterator; @@ -2162,7 +2289,12 @@ 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; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; cl_iterator() BOOST_NOEXCEPT : ptr_() {} @@ -2213,11 +2345,7 @@ namespace boost { } }; - template - struct iterator - : public std::iterator + template struct iterator { #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template @@ -2230,7 +2358,12 @@ 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; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; iterator() BOOST_NOEXCEPT : node_() {} @@ -2267,11 +2400,7 @@ namespace boost { } }; - template - struct c_iterator - : public std::iterator + template struct c_iterator { friend struct boost::unordered::iterator_detail::iterator; @@ -2285,7 +2414,12 @@ 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; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; c_iterator() BOOST_NOEXCEPT : node_() {} @@ -2412,7 +2546,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_address(p)); node_allocator_traits::deallocate(constructor_.alloc_, p, 1); } } @@ -2590,20 +2724,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 { @@ -2614,10 +2741,11 @@ 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::is_nothrow_swappable::value && + boost::is_nothrow_swappable

::value; private: - friend class boost::unordered::detail::set_hash_functions; functions& operator=(functions const&); typedef compressed function_pair; @@ -2625,134 +2753,101 @@ 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]; - function_pair const& current() const - { - return *static_cast( - static_cast(funcs_[current_].address())); - } - - function_pair& current() - { - return *static_cast( - static_cast(funcs_[current_].address())); - } - - void construct(bool which, H const& hf, P const& eq) - { - new ((void*)&funcs_[which]) function_pair(hf, eq); - } - - void construct(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( - 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) - { - 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) + functions(H const& hf, P const& eq) : current_(0) { - construct(current_, hf, eq); + construct_functions(current_, hf, eq); } - functions(functions const& bf) : current_(false) + functions(functions const& bf) : current_(0) { - construct(current_, bf.current()); + construct_functions(current_, bf.current_functions()); } functions(functions& bf, boost::unordered::detail::move_tag) - : current_(false) + : current_(0) { - construct(current_, bf.current(), + construct_functions(current_, bf.current_functions(), boost::unordered::detail::integral_constant()); } - ~functions() { this->destroy(current_); } - - H const& hash_function() const { return current().first(); } - - P const& key_eq() const { return current().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_) + ~functions() { - f.construct(tmp_functions_, h, p); + BOOST_ASSERT(!(current_ & 2)); + destroy_functions(current_); } - set_hash_functions(functions_type& f, functions_type const& other) - : functions_(f), tmp_functions_(!f.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 { - f.construct(tmp_functions_, other.current()); + return *static_cast( + static_cast(funcs_[current_ & 1].address())); } - ~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) + function_pair& current_functions() { + return *static_cast( + static_cast(funcs_[current_ & 1].address())); } - set_hash_functions(functions_type& f, functions_type const& other) - : functions_(f), hash_(other.hash_function()), pred_(other.key_eq()) + void construct_spare_functions(function_pair const& f) { + BOOST_ASSERT(!(current_ & 2)); + construct_functions(current_ ^ 1, f); + current_ |= 2; } - void commit() + void cleanup_spare_functions() { - functions_.current().first() = boost::move(hash_); - functions_.current().second() = boost::move(pred_); + if (current_ & 2) { + current_ = static_cast(current_ & 1); + destroy_functions(current_ ^ 1); + } + } + + void switch_functions() + { + BOOST_ASSERT(current_ & 2); + destroy_functions(static_cast(current_ & 1)); + current_ ^= 3; + } + + private: + 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(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(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(unsigned char which) + { + BOOST_ASSERT(!(which & 2)); + boost::unordered::detail::func::destroy( + (function_pair*)(&funcs_[which])); } }; @@ -2801,31 +2896,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 @@ -2853,7 +2923,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_wrap(bucket_index); @@ -2959,12 +3028,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 @@ -3093,7 +3162,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(); } @@ -3137,9 +3206,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_address(i)) bucket(); } - new (pointer::get(end)) bucket(dummy_node); + new ((void*)boost::to_address(end)) bucket(dummy_node); } //////////////////////////////////////////////////////////////////////// @@ -3160,14 +3229,24 @@ namespace boost { allocators_.swap(other.allocators_); } - // Only swaps the allocators if propagate_on_container_swap - void swap(table& x) + // Not nothrow swappable + void swap(table& x, false_type) { - set_hash_functions op1(*this, x); - set_hash_functions op2(x, *this); + if (this == &x) { + return; + } + + this->construct_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(); - // I think swap can throw if Propagate::value, - // since the allocators' swap can throw. Not sure though. swap_allocators( x, boost::unordered::detail::integral_constant::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 @@ -3207,9 +3312,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(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())); @@ -3217,7 +3322,7 @@ namespace boost { prev->next_ = n2; ++size_; prev = n2; - last_bucket = bucket; + last_bucket = n_bucket; } } } @@ -3231,19 +3336,19 @@ 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_address(n)); node_allocator_traits::deallocate(node_alloc(), n, 1); } void delete_buckets() { if (buckets_) { - node_pointer n = - static_cast(get_bucket(bucket_count_)->next_); + node_pointer n = static_cast( + get_bucket_pointer(bucket_count_)->next_); 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_address(n)); node_allocator_traits::deallocate(node_alloc(), n, 1); n = next; } @@ -3263,9 +3368,9 @@ 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)); + boost::unordered::detail::func::destroy(boost::to_address(it)); } bucket_allocator_traits::deallocate( @@ -3293,11 +3398,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(); } @@ -3328,18 +3433,25 @@ namespace boost { void assign(table const& x, UniqueType is_unique, false_type) { // Strong exception safety. - 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(); assign_buckets(x, is_unique); } @@ -3350,7 +3462,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. @@ -3358,7 +3471,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_); @@ -3380,30 +3492,52 @@ namespace boost { } } + // Propagate allocator template void move_assign(table& x, UniqueType, true_type) { + 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(); - set_hash_functions new_func_this(*this, x); allocators_.move_assign(x.allocators_); - // No throw from here. mlf_ = x.mlf_; move_buckets_from(x); - new_func_this.commit(); } + // Don't propagate allocator template void move_assign(table& x, UniqueType is_unique, false_type) { 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); } else { - set_hash_functions new_func_this(*this, x); + move_assign_realloc(x, is_unique); + } + } + + void move_assign_equal_alloc(table& 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); + } + + template + void move_assign_realloc(table& x, UniqueType is_unique) + { + this->construct_spare_functions(x.current_functions()); + BOOST_TRY + { mlf_ = x.mlf_; recalculate_max_load(); @@ -3412,11 +3546,15 @@ namespace boost { } else if (size_) { clear_buckets(); } - - new_func_this.commit(); - - move_assign_buckets(x, is_unique); } + BOOST_CATCH(...) + { + this->cleanup_spare_functions(); + BOOST_RETHROW + } + BOOST_CATCH_END + this->switch_functions(); + move_assign_buckets(x, is_unique); } // Accessors @@ -3547,7 +3685,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(); @@ -3556,7 +3694,8 @@ 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; @@ -4068,18 +4207,19 @@ 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; } @@ -4105,7 +4245,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_; @@ -4374,7 +4514,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(); } @@ -4462,7 +4602,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; diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index bae3aa2f..1910219c 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -26,10 +26,12 @@ #if defined(BOOST_MSVC) #pragma warning(push) +// conditional expression is constant +#pragma warning(disable : 4127) #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 +// the inline specifier cannot be used when a friend declaration refers to a +// specialization of a function template +#pragma warning(disable : 4396) #endif #endif @@ -151,10 +153,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 +169,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; @@ -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::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -831,6 +830,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 { @@ -949,10 +1023,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; @@ -966,10 +1039,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; @@ -1252,11 +1324,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::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -1363,6 +1434,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 @@ -1598,10 +1736,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::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value) { table_.swap(other.table_); } @@ -2075,10 +2212,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::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value) { table_.swap(other.table_); } @@ -2314,72 +2450,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(); @@ -2393,7 +2508,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() @@ -2402,38 +2517,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 e01c5586..dfc24e85 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -25,10 +25,12 @@ #if defined(BOOST_MSVC) #pragma warning(push) +// conditional expression is constant +#pragma warning(disable : 4127) #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 +// the inline specifier cannot be used when a friend declaration refers to a +// specialization of a function template +#pragma warning(disable : 4396) #endif #endif @@ -149,10 +151,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 +167,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; @@ -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::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -545,6 +544,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) @@ -661,10 +706,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; @@ -678,10 +722,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; @@ -945,11 +988,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::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value); void clear() BOOST_NOEXCEPT { table_.clear_impl(); } template @@ -1049,6 +1091,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() @@ -1270,10 +1361,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::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value) { table_.swap(other.table_); } @@ -1665,10 +1755,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::is_nothrow_swappable::value&& + boost::is_nothrow_swappable

::value) { table_.swap(other.table_); } @@ -1875,15 +1964,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: @@ -1894,52 +1979,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(); @@ -1948,7 +2020,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() @@ -1957,38 +2029,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 diff --git a/meta/explicit-failures-markup.xml b/meta/explicit-failures-markup.xml index 7ab7ce7e..25a19e3d 100644 --- a/meta/explicit-failures-markup.xml +++ b/meta/explicit-failures-markup.xml @@ -1,4 +1,10 @@ + @@ -17,11 +23,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. + + + 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/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 f0e55ae7..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(); @@ -146,23 +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) - { - return impl(x); + return insert_lvalue_pos_type_impl(x); } } insert_lvalue_pos; @@ -198,23 +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) - { - return impl(x); + return emplace_lvalue_pos_type_impl(x); } } emplace_lvalue_pos; 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/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 242410d7..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), @@ -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/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..bd27d8df 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 @@ -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 5f816cfe..146dea4d 100644 --- a/test/helpers/helpers.hpp +++ b/test/helpers/helpers.hpp @@ -6,10 +6,12 @@ #if !defined(BOOST_UNORDERED_TEST_HELPERS_HEADER) #define BOOST_UNORDERED_TEST_HELPERS_HEADER +#include + 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; } @@ -28,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); } @@ -36,16 +38,17 @@ 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, + static_cast::difference_type>(x)); return it; } } diff --git a/test/helpers/input_iterator.hpp b/test/helpers/input_iterator.hpp index 18e6695d..7a938a50 100644 --- a/test/helpers/input_iterator.hpp +++ b/test/helpers/input_iterator.hpp @@ -7,13 +7,12 @@ #define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER #include -#include #include 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_) {} @@ -25,16 +24,13 @@ namespace test { proxy& operator=(proxy const&); }; - template - struct input_iterator_adaptor - : public std::iterator::type, - std::ptrdiff_t, - BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type, - proxy > + template struct input_iterator_adaptor { - typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type - value_type; + 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; input_iterator_adaptor() : base_() {} explicit input_iterator_adaptor(Iterator& it) : base_(&it) {} @@ -66,19 +62,15 @@ namespace test { return input_iterator_adaptor(it); } - 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, - proxy > + template struct copy_iterator_adaptor { - typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type - value_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference::type - difference_type; + 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_() {} explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {} 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/list.hpp b/test/helpers/list.hpp index 137cb17c..d39c766e 100644 --- a/test/helpers/list.hpp +++ b/test/helpers/list.hpp @@ -81,9 +81,7 @@ namespace test { list_data& operator=(list_data const&); }; - template - class list_iterator - : public std::iterator + template class list_iterator { friend class list_const_iterator; friend class test::list; @@ -93,6 +91,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) {} @@ -113,9 +117,7 @@ namespace test { bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; } }; - template - class list_const_iterator : public std::iterator + template class list_const_iterator { friend class list_iterator; friend class test::list; @@ -126,6 +128,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_) {} 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/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/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/objects/test.hpp b/test/objects/test.hpp index 8ea6d2de..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,10 +358,9 @@ namespace test { typedef allocator1 other; }; - explicit allocator1(int t = 0) : tag_(t) - { - detail::tracker.allocator_ref(); - } + allocator1() : tag_(0) { detail::tracker.allocator_ref(); } + + explicit allocator1(int t) : tag_(t) { detail::tracker.allocator_ref(); } template allocator1(allocator1 const& x) : tag_(x.tag_) { @@ -601,10 +604,9 @@ namespace test { typedef allocator2 other; }; - explicit allocator2(int t = 0) : tag_(t) - { - detail::tracker.allocator_ref(); - } + allocator2() : tag_(0) { detail::tracker.allocator_ref(); } + + explicit allocator2(int t) : tag_(t) { detail::tracker.allocator_ref(); } template allocator2(allocator2 const& x) : tag_(x.tag_) { diff --git a/test/unordered/allocator_traits.cpp b/test/unordered/allocator_traits.cpp index 9b8738c2..476205b7 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 @@ -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) \ @@ -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); } 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/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; 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 0a6176ad..bb5256f8 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 @@ -51,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 boost::iterator_value::type - iterator_value_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type + typedef + typename std::iterator_traits::value_type iterator_value_type; + typedef typename std::iterator_traits::value_type const_iterator_value_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference::type + typedef typename std::iterator_traits::difference_type iterator_difference_type; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference< - const_iterator>::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 @@ -96,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 @@ -207,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; @@ -246,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 boost::iterator_pointer::type - iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef typename X::iterator iterator; + typedef typename X::const_iterator const_iterator; + typedef typename X::local_iterator local_iterator; + typedef typename X::const_local_iterator const_local_iterator; + typedef typename std::iterator_traits::pointer iterator_pointer; + typedef typename std::iterator_traits::pointer const_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef typename std::iterator_traits::pointer local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer< - const_local_iterator>::type const_local_iterator_pointer; + typedef typename std::iterator_traits::pointer + const_local_iterator_pointer; BOOST_STATIC_ASSERT( (boost::is_same::value)); @@ -281,8 +281,46 @@ template void unordered_set_test(X& r, Key const&) BOOST_STATIC_ASSERT( (boost::is_same::value)); - typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; - typedef BOOST_DEDUCED_TYPENAME node_type::value_type node_value_type; + // 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 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. @@ -297,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 boost::iterator_pointer::type - iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef typename X::iterator iterator; + typedef typename X::const_iterator const_iterator; + typedef typename X::local_iterator local_iterator; + typedef typename X::const_local_iterator const_local_iterator; + typedef typename std::iterator_traits::pointer iterator_pointer; + typedef typename std::iterator_traits::pointer const_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type + typedef typename std::iterator_traits::pointer local_iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer< - const_local_iterator>::type const_local_iterator_pointer; + typedef typename std::iterator_traits::pointer + const_local_iterator_pointer; BOOST_STATIC_ASSERT((boost::is_same::value)); BOOST_STATIC_ASSERT( @@ -326,9 +363,47 @@ void unordered_map_test(X& r, Key const& k, T const& v) BOOST_STATIC_ASSERT( (boost::is_same::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; + // 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 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)); @@ -400,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 @@ -432,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)); } @@ -440,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]); @@ -472,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 boost::BOOST_ITERATOR_CATEGORY::type + typedef typename std::iterator_traits::iterator_category iterator_category; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference::type + typedef typename std::iterator_traits::difference_type iterator_difference; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer::type - iterator_pointer; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference::type - iterator_reference; + typedef typename std::iterator_traits::pointer iterator_pointer; + typedef 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 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 boost::iterator_reference::type + typedef 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 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 boost::iterator_reference::type + typedef 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 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 >(); @@ -636,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 @@ -734,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()); } @@ -745,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/deduction_tests.cpp b/test/unordered/deduction_tests.cpp new file mode 100644 index 00000000..673c0609 --- /dev/null +++ b/test/unordered/deduction_tests.cpp @@ -0,0 +1,352 @@ + +// Copyright 2017-2018 Daniel James. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#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 +} 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 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 ae305881..14338738 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 { @@ -33,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(); @@ -65,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); @@ -90,23 +87,21 @@ 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 { - 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); - BOOST_DEDUCED_TYPENAME Container::key_type key = - test::get_key(*pos); + next = test::next(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); --size; if (size > 0) - BOOST_TEST( - index == 0 ? next == x.begin() : next == boost::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/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/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)); 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 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 a8e2fa28..2d5b1eab 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 @@ -146,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); @@ -194,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(); @@ -247,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()); @@ -268,14 +267,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); @@ -292,25 +291,24 @@ 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(); - 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); @@ -326,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()); @@ -341,12 +339,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); } } diff --git a/test/unordered/noexcept_tests.cpp b/test/unordered/noexcept_tests.cpp index 98dfa2b2..454e7c23 100644 --- a/test/unordered/noexcept_tests.cpp +++ b/test/unordered/noexcept_tests.cpp @@ -12,17 +12,31 @@ #include "../helpers/test.hpp" +#if defined(BOOST_MSVC) +#pragma warning(push) +// conditional expression is constant +#pragma warning(disable : 4127) +#endif + namespace noexcept_tests { // Test the noexcept is set correctly for the move constructor. struct hash_possible_exception : boost::hash { 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 @@ -42,25 +56,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,54 +93,109 @@ 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_construct; + typedef hash_nothrow hash_nothrow_move_assign; + typedef hash_nothrow hash_nothrow_swap; - 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_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); - have_is_nothrow_move = - boost::is_nothrow_move_constructible::value; + BOOST_TEST( + !boost::is_nothrow_move_assignable::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::is_nothrow_swappable< + equal_to_nothrow >::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. + have_is_nothrow_move = + boost::is_nothrow_move_constructible::value; + have_is_nothrow_move_assign = + boost::is_nothrow_move_assignable::value; + have_is_nothrow_swap = + boost::is_nothrow_swappable::value; + +// Check that the traits work when expected. #if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && \ !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) BOOST_TEST(have_is_nothrow_move); + BOOST_TEST(have_is_nothrow_move_assign); #endif + +#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_NOEXCEPT) && \ + !defined(BOOST_NO_CXX11_DECLTYPE) && \ + !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + BOOST_TEST(have_is_nothrow_swap); +#endif + + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << "have_is_nothrow_move: " << have_is_nothrow_move << std::endl + << "have_is_nothrow_swap: " << have_is_nothrow_swap << std::endl; } UNORDERED_AUTO_TEST (test_noexcept) { @@ -137,32 +217,104 @@ 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) { + typedef boost::unordered_set + throwing_set; + + if (have_is_nothrow_swap) { + BOOST_TEST(boost::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; } } +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + RUN_TESTS() 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));