mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Merge branch 'develop'
This commit is contained in:
58
.travis.yml
58
.travis.yml
@ -18,49 +18,47 @@ addons:
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=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: BJAM_TOOLSET=gcc-std11
|
||||
#- compiler: gcc
|
||||
# env: BJAM_TOOLSET=gcc-m32
|
||||
env: |
|
||||
label="gcc C++11";
|
||||
user_config="using gcc : : g++-4.8 --coverage -fsanitize=address -Werror --std=c++11 ;"
|
||||
enable_coverage=1
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc-std11m32
|
||||
#- compiler: clang
|
||||
# env: BJAM_TOOLSET=clang
|
||||
env: |
|
||||
label="gcc 32 bit C++11";
|
||||
user_config="using gcc : : g++-4.8 -m32 -fsanitize=address -Werror --std=c++11 ;"
|
||||
- compiler: clang
|
||||
env: BJAM_TOOLSET=clang-std11
|
||||
env: |
|
||||
label="clang C++11";
|
||||
user_config="using clang : : clang++ -fsanitize=address -Werror --std=c++11 ;"
|
||||
# sanitized=address not available for 32-bit clang on travis.
|
||||
- compiler: clang
|
||||
env: BJAM_TOOLSET=clang-m32
|
||||
#- compiler: clang
|
||||
# env: BJAM_TOOLSET=clang-std11m32
|
||||
- compiler: gcc
|
||||
env: BJAM_TOOLSET=gcc-interopable
|
||||
- compiler: clang
|
||||
env: BJAM_TOOLSET=clang-interopable
|
||||
env: |
|
||||
label="clang 32 bit";
|
||||
user_config="using clang : : clang++ -m32 -Werror --std=c++03 ;"
|
||||
|
||||
before_install:
|
||||
- if [ -n $enable_coverage ]; then pip install --user cpp-coveralls; fi
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- touch Jamroot.jam
|
||||
- cd $HOME
|
||||
- |
|
||||
echo "using gcc : : g++-4.8 -Werror --std=c++03 -fsanitize=address ;" > ~/user-config.jam
|
||||
echo "using gcc : std11 : g++-4.8 -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using gcc : m32 : g++-4.8 -m32 -Werror -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using gcc : std11m32 : g++-4.8 -m32 -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using clang : : clang++ -Werror --std=c++03 -fsanitize=address ;" >> ~/user-config.jam
|
||||
echo "using clang : std11 : clang++ -Werror --std=c++11 -fsanitize=address ;" >> ~/user-config.jam
|
||||
# sanitized=address not available for 32-bit clang on travis.
|
||||
echo "using clang : m32 : clang++ -m32 -Werror --std=c++03 ;" >> ~/user-config.jam
|
||||
echo "using clang : std11m32 : clang++ -m32 -Werror --std=c++11 ;" >> ~/user-config.jam
|
||||
echo "using gcc : interopable : g++-4.8 -Werror --std=c++03 -fsanitize=address -DBOOST_UNORDERED_INTEROPERABLE_NODES=1 ;" >> ~/user-config.jam
|
||||
echo "using clang : interopable : clang++ -Werror --std=c++11 -fsanitize=address -DBOOST_UNORDERED_INTEROPERABLE_NODES=1 ;" >> ~/user-config.jam
|
||||
- echo $user_config > ~/user-config.jam
|
||||
- cat ~/user-config.jam
|
||||
- wget -O boost.tar.bz2 https://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.bz2
|
||||
- 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_63_0 boost
|
||||
- mv boost_1_64_0 boost
|
||||
- rm -r boost/boost/unordered
|
||||
|
||||
after_success:
|
||||
if [ -n $enable_coverage ]; then coveralls -r ${TRAVIS_BUILD_DIR} -b ${TRAVIS_BUILD_DIR}/test --gcov-options '\-lp' --include include/boost/unordered/ ; fi
|
||||
|
||||
script:
|
||||
- cd ${TRAVIS_BUILD_DIR}/test
|
||||
- bjam ${BJAM_TOOLSET} include=${HOME}/boost include=${TRAVIS_BUILD_DIR}/include
|
||||
- bjam -q include=${HOME}/boost include=${TRAVIS_BUILD_DIR}/include
|
||||
- xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml
|
||||
|
@ -99,7 +99,7 @@ First official release.
|
||||
has been rewritten to use templates instead of macros for the implementation
|
||||
classes.
|
||||
|
||||
* The container objcet is now smaller thanks to using `boost::compressed_pair`
|
||||
* The container object is now smaller thanks to using `boost::compressed_pair`
|
||||
for EBO and a slightly different function buffer - now using a bool instead
|
||||
of a member pointer.
|
||||
|
||||
@ -170,7 +170,7 @@ C++11 support has resulted in some breaking changes:
|
||||
longer does so. It does emulate the new `piecewise_construct`
|
||||
pair constructors - only you need to use
|
||||
`boost::piecewise_construct`. To use the old emulation of
|
||||
the variadic consturctors define
|
||||
the variadic constructors define
|
||||
`BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT`.
|
||||
|
||||
[h2 Boost 1.49.0]
|
||||
@ -207,7 +207,7 @@ C++11 support has resulted in some breaking changes:
|
||||
* Fix construction/destruction issue when using a C++11 compiler with a
|
||||
C++03 allocator ([ticket 7100]).
|
||||
* Remove a `try..catch` to support compiling without exceptions.
|
||||
* Adjust SFINAE use to try to supprt g++ 3.4 ([ticket 7175]).
|
||||
* Adjust SFINAE use to try to support g++ 3.4 ([ticket 7175]).
|
||||
* Updated to use the new config macros.
|
||||
|
||||
[h2 Boost 1.52.0]
|
||||
@ -307,9 +307,17 @@ C++11 support has resulted in some breaking changes:
|
||||
* Initial support for new C++17 member functions:
|
||||
`insert_or_assign` and `try_emplace` in `unordered_map`,
|
||||
* Initial support for `merge` and `extract`.
|
||||
Does not include transfering nodes between
|
||||
Does not include transferring nodes between
|
||||
`unordered_map` and `unordered_multimap` or between `unordered_set` and
|
||||
`unordered_multiset` yet. That will hopefully be in the next version of
|
||||
Boost.
|
||||
|
||||
[h2 Boost 1.65.0]
|
||||
|
||||
* Add deprecated attributes to `quick_erase` and `erase_return_void`.
|
||||
I really will remove them in a future version this time.
|
||||
* Small standards compliance fixes:
|
||||
* `noexpect` specs for `swap` free functions.
|
||||
* Add missing `insert(P&&)` methods.
|
||||
|
||||
[endsect]
|
||||
|
@ -2,7 +2,13 @@
|
||||
/ 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) ]
|
||||
|
||||
[section:compliance C++11 Compliance]
|
||||
[section:compliance Standard Compliance]
|
||||
|
||||
The intent of Boost.Unordered is to implement a close (but inperfect)
|
||||
implementation of the C++17 standard, that will work with C++98 upwards.
|
||||
The wide compatibility does mean some comprimises have to be made.
|
||||
With a compiler and library that fully support C++11, the differences should
|
||||
be minor.
|
||||
|
||||
[section:move Move emulation]
|
||||
|
||||
@ -51,23 +57,32 @@ Due to imperfect move emulation, some assignments might check
|
||||
`propagate_on_container_copy_assignment` on some compilers and
|
||||
`propagate_on_container_move_assignment` on others.
|
||||
|
||||
The use of the allocator's construct and destruct methods might be a bit
|
||||
surprising.
|
||||
Nodes are constructed and destructed using the allocator, but the elements
|
||||
are stored in aligned space within the node and constructed and destructed
|
||||
by calling the constructor and destructor directly.
|
||||
[endsect]
|
||||
|
||||
In C++11 the allocator's construct function has the signature:
|
||||
[section:construction Construction/Destruction using allocators]
|
||||
|
||||
template <class U, class... Args>
|
||||
void construct(U* p, Args&&... args);
|
||||
The following support is required for full use of C++11 style
|
||||
construction/destruction:
|
||||
|
||||
which supports calling `construct` for the contained object, but
|
||||
most existing allocators don't support this. If member function detection
|
||||
was good enough then with old allocators it would fall back to calling
|
||||
the element's constructor directly but in general, detection isn't good
|
||||
enough to do this which is why Boost.Unordered just calls the constructor
|
||||
directly every time. In most cases this will work okay.
|
||||
* Variadic templates.
|
||||
* Piecewise construction of `std::pair`.
|
||||
* Either `std::allocator_traits` or expression SFINAE.
|
||||
|
||||
This is detected using Boost.Config. The macro
|
||||
`BOOST_UNORDERED_CXX11_CONSTRUCTION` will be set to 1 if it is found, or 0
|
||||
otherwise.
|
||||
|
||||
When this is the case `allocator_traits::construct` and
|
||||
`allocator_traits::destroy` will always be used, apart from when piecewise
|
||||
constructing a `std::pair` using `boost::tuple` (see [link
|
||||
unordered.compliance.pairs below]), but that should be easily avoided.
|
||||
|
||||
When support is not available `allocator_traits::construct` and
|
||||
`allocator_traits::destroy` are never called.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:pointer_traits Pointer Traits]
|
||||
|
||||
`pointer_traits` aren't used. Instead, pointer types are obtained from
|
||||
rebound allocators, this can cause problems if the allocator can't be
|
||||
@ -77,6 +92,7 @@ is used to obtain a const pointer.
|
||||
|
||||
[endsect]
|
||||
|
||||
[#unordered.compliance.pairs]
|
||||
[section:pairs Pairs]
|
||||
|
||||
Since the containers use `std::pair` they're limited to the version
|
||||
|
@ -13,7 +13,7 @@ containers in the draft standard, so the interface was fixed. But there are
|
||||
still some implementation decisions to make. The priorities are
|
||||
conformance to the standard and portability.
|
||||
|
||||
The [@http://en.wikipedia.org/wiki/Hash_table wikipedia article on hash tables]
|
||||
The [@http://en.wikipedia.org/wiki/Hash_table Wikipedia article on hash tables]
|
||||
has a good summary of the implementation issues for hash tables in general.
|
||||
|
||||
[h2 Data Structure]
|
||||
@ -100,7 +100,7 @@ knowledge of the number of bits in the hash value, so it isn't portable enough
|
||||
to use as a default. It can applicable in certain cases so the containers
|
||||
have a policy based implementation that can use this alternative technique.
|
||||
|
||||
Currently this is only done on 64 bit architecures, where prime number
|
||||
Currently this is only done on 64 bit architectures, where prime number
|
||||
modulus can be expensive. Although this varies depending on the architecture,
|
||||
so I probably should revisit it.
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#endif
|
||||
#elif defined(_LIBCPP_VERSION)
|
||||
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
|
||||
#if LIBCPP_VERSION >= 3000
|
||||
#if _LIBCPP_VERSION >= 3000
|
||||
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
|
||||
#endif
|
||||
#elif defined(BOOST_MSVC)
|
||||
@ -32,6 +32,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// TODO: Use piecewise construction by default? Is it safe to assume that an
|
||||
// unknown library has it?
|
||||
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
|
||||
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 0
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -27,65 +27,22 @@ template <typename A, typename K, typename M, typename H, typename P> struct map
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::table<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<value_type> extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::l_iterator<node, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
typedef boost::unordered::iterator_detail::l_iterator<node> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node> cl_iterator;
|
||||
|
||||
typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
|
||||
typedef boost::unordered::insert_return_type_map<node, K, M, A>
|
||||
insert_return_type;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct multimap
|
||||
{
|
||||
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
|
||||
|
||||
typedef std::pair<K const, M> value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef K const const_key_type;
|
||||
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<A,
|
||||
value_type>::type value_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
value_allocator_traits;
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
#else
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
#endif
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<value_type> extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::l_iterator<node, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
|
||||
typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
|
||||
};
|
||||
|
||||
template <typename K, typename M, typename H, typename P, typename A>
|
||||
class instantiate_map
|
||||
{
|
||||
|
@ -27,64 +27,22 @@ template <typename A, typename T, typename H, typename P> struct set
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::table_impl<types> table;
|
||||
typedef boost::unordered::detail::table<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node> l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node> cl_iterator;
|
||||
|
||||
typedef boost::unordered::node_handle_set<node, T, A> node_type;
|
||||
typedef boost::unordered::insert_return_type_set<node, T, A>
|
||||
insert_return_type;
|
||||
};
|
||||
|
||||
template <typename A, typename T, typename H, typename P> struct multiset
|
||||
{
|
||||
typedef boost::unordered::detail::multiset<A, T, H, P> types;
|
||||
|
||||
typedef T value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef T const const_key_type;
|
||||
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<A,
|
||||
value_type>::type value_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
value_allocator_traits;
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
#else
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
#endif
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::grouped_table_impl<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
|
||||
typedef boost::unordered::node_handle_set<node, T, A> node_type;
|
||||
};
|
||||
|
||||
template <typename T, typename H, typename P, typename A> class instantiate_set
|
||||
{
|
||||
typedef boost::unordered_set<T, H, P, A> container;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,9 @@ template <class K, class T, class H, class P, class A>
|
||||
inline bool operator!=(
|
||||
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline void swap(unordered_map<K, T, H, P, A>&, unordered_map<K, T, H, P, A>&);
|
||||
inline void swap(
|
||||
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
|
||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
||||
|
||||
template <class K, class T, class H = boost::hash<K>,
|
||||
class P = std::equal_to<K>,
|
||||
@ -44,8 +46,9 @@ template <class K, class T, class H, class P, class A>
|
||||
inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
|
||||
unordered_multimap<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
inline void swap(
|
||||
unordered_multimap<K, T, H, P, A>&, unordered_multimap<K, T, H, P, A>&);
|
||||
inline void swap(unordered_multimap<K, T, H, P, A>& m1,
|
||||
unordered_multimap<K, T, H, P, A>& m2)
|
||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
||||
|
||||
template <class N, class K, class T, class A> class node_handle_map;
|
||||
template <class N, class K, class T, class A> struct insert_return_type_map;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,8 @@ template <class T, class H, class P, class A>
|
||||
inline bool operator!=(
|
||||
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
inline void swap(unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2);
|
||||
inline void swap(unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
|
||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
||||
|
||||
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
|
||||
class A = std::allocator<T> >
|
||||
@ -43,7 +44,8 @@ inline bool operator!=(unordered_multiset<T, H, P, A> const&,
|
||||
unordered_multiset<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
inline void swap(
|
||||
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2);
|
||||
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
|
||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
||||
|
||||
template <class N, class T, class A> class node_handle_set;
|
||||
template <class N, class T, class A> struct insert_return_type_set;
|
||||
|
@ -15,6 +15,7 @@ project unordered-test/unordered
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>clang:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>msvc:<cxxflags>"/wd4494"
|
||||
<toolset>gcc:<c++-template-depth>500
|
||||
;
|
||||
|
||||
#alias framework : /boost/test//boost_unit_test_framework ;
|
||||
@ -45,7 +46,7 @@ test-suite unordered
|
||||
[ run unordered/insert_hint_tests.cpp ]
|
||||
[ run unordered/emplace_tests.cpp ]
|
||||
[ run unordered/unnecessary_copy_tests.cpp ]
|
||||
[ run unordered/erase_tests.cpp ]
|
||||
[ run unordered/erase_tests.cpp : : : <define>BOOST_UNORDERED_SUPPRESS_DEPRECATED ]
|
||||
[ run unordered/erase_equiv_tests.cpp ]
|
||||
[ run unordered/extract_tests.cpp ]
|
||||
[ run unordered/node_handle_tests.cpp ]
|
||||
@ -61,6 +62,7 @@ test-suite unordered
|
||||
[ run unordered/rehash_tests.cpp ]
|
||||
[ run unordered/equality_tests.cpp ]
|
||||
[ run unordered/swap_tests.cpp ]
|
||||
[ run unordered/detail_tests.cpp ]
|
||||
|
||||
[ run unordered/compile_set.cpp : :
|
||||
: <define>BOOST_UNORDERED_USE_MOVE
|
||||
@ -90,4 +92,5 @@ test-suite unordered-exception
|
||||
[ run exception/rehash_exception_tests.cpp framework ]
|
||||
[ run exception/swap_exception_tests.cpp framework : : :
|
||||
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
|
||||
[ run exception/merge_exception_tests.cpp framework ]
|
||||
;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable : 4512) // assignment operator could not be generated
|
||||
@ -17,11 +18,22 @@ test::seed_t initialize_seed(12847);
|
||||
template <class T> struct self_assign_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
self_assign_base(std::size_t count = 0) : values(count) {}
|
||||
self_assign_base(std::size_t count = 0) : values(count, test::limited_range)
|
||||
{
|
||||
}
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(values.begin(), values.end()); }
|
||||
void run(T& x) const { x = x; }
|
||||
|
||||
void run(T& x) const
|
||||
{
|
||||
x = x;
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
|
||||
{
|
||||
test::check_equivalent_keys(x);
|
||||
@ -57,7 +69,16 @@ template <class T> struct assign_base : public test::exception_base
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(x); }
|
||||
void run(T& x1) const { x1 = y; }
|
||||
|
||||
void run(T& x1) const
|
||||
{
|
||||
x1 = y;
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x1, y_values);
|
||||
test::check_equivalent_keys(x1);
|
||||
}
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
|
||||
{
|
||||
test::check_equivalent_keys(x1);
|
||||
@ -76,11 +97,12 @@ template <class T> struct assign_base : public test::exception_base
|
||||
template <class T> struct assign_values : assign_base<T>
|
||||
{
|
||||
assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2,
|
||||
float mlf1 = 1.0, float mlf2 = 1.0)
|
||||
test::random_generator gen = test::default_generator, float mlf1 = 1.0,
|
||||
float mlf2 = 1.0)
|
||||
: assign_base<T>(tag1, tag2, mlf1, mlf2)
|
||||
{
|
||||
this->x_values.fill(count1);
|
||||
this->y_values.fill(count2);
|
||||
this->x_values.fill(count1, gen);
|
||||
this->y_values.fill(count2, gen);
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
@ -96,11 +118,21 @@ template <class T> struct assign_test2 : assign_values<T>
|
||||
assign_test2() : assign_values<T>(60, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test2a : assign_values<T>
|
||||
{
|
||||
assign_test2a() : assign_values<T>(60, 0, 0, 0, test::limited_range) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test3 : assign_values<T>
|
||||
{
|
||||
assign_test3() : assign_values<T>(0, 60, 0, 0) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test3a : assign_values<T>
|
||||
{
|
||||
assign_test3a() : assign_values<T>(0, 60, 0, 0, test::limited_range) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test4 : assign_values<T>
|
||||
{
|
||||
assign_test4() : assign_values<T>(10, 10, 1, 2) {}
|
||||
@ -111,9 +143,17 @@ template <class T> struct assign_test4a : assign_values<T>
|
||||
assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test4b : assign_values<T>
|
||||
{
|
||||
assign_test4b() : assign_values<T>(10, 100, 1, 2, test::limited_range) {}
|
||||
};
|
||||
|
||||
template <class T> struct assign_test5 : assign_values<T>
|
||||
{
|
||||
assign_test5() : assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
|
||||
assign_test5()
|
||||
: assign_values<T>(5, 60, 0, 0, test::default_generator, 1.0f, 0.1f)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct equivalent_test1 : assign_base<T>
|
||||
@ -131,8 +171,15 @@ template <class T> struct equivalent_test1 : assign_base<T>
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((self_assign_test1)(self_assign_test2)(assign_test1)(
|
||||
assign_test2)(assign_test3)(assign_test4)(assign_test4a)(
|
||||
assign_test5)(equivalent_test1),
|
||||
// clang-format off
|
||||
EXCEPTION_TESTS_REPEAT(5,
|
||||
(self_assign_test1)(self_assign_test2)
|
||||
(assign_test1)(assign_test2)(assign_test2a)
|
||||
(assign_test3)(assign_test3a)
|
||||
(assign_test4)(assign_test4a)(assign_test4b)
|
||||
(assign_test5)
|
||||
(equivalent_test1),
|
||||
CONTAINER_SEQ)
|
||||
// clang-format on
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -6,7 +6,9 @@
|
||||
#include "./containers.hpp"
|
||||
|
||||
#include "../helpers/input_iterator.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
|
||||
template <typename T> inline void avoid_unused_warning(T const&) {}
|
||||
|
||||
@ -25,7 +27,10 @@ template <class T> struct construct_test1 : public objects, test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T x;
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
BOOST_TEST(x.empty());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -34,7 +39,10 @@ template <class T> struct construct_test2 : public objects, test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T x(300);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
BOOST_TEST(x.empty());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -43,7 +51,10 @@ template <class T> struct construct_test3 : public objects, test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T x(0, hash);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
BOOST_TEST(x.empty());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -52,7 +63,10 @@ template <class T> struct construct_test4 : public objects, test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T x(0, hash, equal_to);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
BOOST_TEST(x.empty());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -61,7 +75,10 @@ template <class T> struct construct_test5 : public objects, test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T x(50, hash, equal_to, allocator);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
BOOST_TEST(x.empty());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -70,7 +87,10 @@ template <class T> struct construct_test6 : public objects, test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T x(allocator);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
BOOST_TEST(x.empty());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -78,8 +98,8 @@ template <class T> struct range : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
|
||||
range() : values(5) {}
|
||||
range(unsigned int count) : values(count) {}
|
||||
range() : values(5, test::limited_range) {}
|
||||
range(unsigned int count) : values(count, test::limited_range) {}
|
||||
};
|
||||
|
||||
template <class T> struct range_construct_test1 : public range<T>, objects
|
||||
@ -87,7 +107,10 @@ template <class T> struct range_construct_test1 : public range<T>, objects
|
||||
void run() const
|
||||
{
|
||||
T x(this->values.begin(), this->values.end());
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -96,7 +119,10 @@ template <class T> struct range_construct_test2 : public range<T>, objects
|
||||
void run() const
|
||||
{
|
||||
T x(this->values.begin(), this->values.end(), 0);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -105,7 +131,10 @@ template <class T> struct range_construct_test3 : public range<T>, objects
|
||||
void run() const
|
||||
{
|
||||
T x(this->values.begin(), this->values.end(), 0, hash);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -114,7 +143,10 @@ template <class T> struct range_construct_test4 : public range<T>, objects
|
||||
void run() const
|
||||
{
|
||||
T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -128,7 +160,10 @@ template <class T> struct range_construct_test5 : public range<T>, objects
|
||||
{
|
||||
T x(this->values.begin(), this->values.end(), 0, hash, equal_to,
|
||||
allocator);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -143,7 +178,10 @@ template <class T> struct input_range_construct_test : public range<T>, objects
|
||||
end = this->values.end();
|
||||
T x(test::input_iterator(begin), test::input_iterator(end), 0, hash,
|
||||
equal_to, allocator);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -156,7 +194,10 @@ template <class T> struct copy_range_construct_test : public range<T>, objects
|
||||
T x(test::copy_iterator(this->values.begin()),
|
||||
test::copy_iterator(this->values.end()), 0, hash, equal_to,
|
||||
allocator);
|
||||
avoid_unused_warning(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,9 @@
|
||||
|
||||
#include "./containers.hpp"
|
||||
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
|
||||
template <typename T> inline void avoid_unused_warning(T const&) {}
|
||||
|
||||
@ -18,7 +20,10 @@ template <class T> struct copy_test1 : public test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T y(x);
|
||||
avoid_unused_warning(y);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
BOOST_TEST(y.empty());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
};
|
||||
|
||||
@ -27,12 +32,18 @@ template <class T> struct copy_test2 : public test::exception_base
|
||||
test::random_values<T> values;
|
||||
T x;
|
||||
|
||||
copy_test2() : values(5), x(values.begin(), values.end()) {}
|
||||
copy_test2()
|
||||
: values(5, test::limited_range), x(values.begin(), values.end())
|
||||
{
|
||||
}
|
||||
|
||||
void run() const
|
||||
{
|
||||
T y(x);
|
||||
avoid_unused_warning(y);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(y, this->values);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
};
|
||||
|
||||
@ -46,7 +57,30 @@ template <class T> struct copy_test3 : public test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T y(x);
|
||||
avoid_unused_warning(y);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(y, this->values);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct copy_test3a : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
T x;
|
||||
|
||||
copy_test3a()
|
||||
: values(100, test::limited_range), x(values.begin(), values.end())
|
||||
{
|
||||
}
|
||||
|
||||
void run() const
|
||||
{
|
||||
T y(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(y, this->values);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
};
|
||||
|
||||
@ -61,10 +95,17 @@ template <class T> struct copy_with_allocator_test : public test::exception_base
|
||||
void run() const
|
||||
{
|
||||
T y(x, allocator);
|
||||
avoid_unused_warning(y);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(y, this->values);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
|
||||
// clang-format off
|
||||
EXCEPTION_TESTS(
|
||||
(copy_test1)(copy_test2)(copy_test3)(copy_test3a)(copy_with_allocator_test),
|
||||
CONTAINER_SEQ)
|
||||
// clang-format on
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -14,7 +14,9 @@ test::seed_t initialize_seed(835193);
|
||||
template <class T> struct erase_test_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
erase_test_base(unsigned int count = 5) : values(count) {}
|
||||
erase_test_base(unsigned int count = 5) : values(count, test::limited_range)
|
||||
{
|
||||
}
|
||||
|
||||
typedef T data_type;
|
||||
|
||||
@ -43,6 +45,10 @@ template <class T> struct erase_by_key_test1 : public erase_test_base<T>
|
||||
it != end; ++it) {
|
||||
x.erase(test::get_key<T>(*it));
|
||||
}
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
BOOST_TEST(x.empty());
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,306 +2,414 @@
|
||||
// Copyright 2006-2009 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "./containers.hpp"
|
||||
|
||||
#include "../helpers/helpers.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/strong.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
test::seed_t initialize_seed(747373);
|
||||
|
||||
template <class T> struct insert_test_base : public test::exception_base
|
||||
// Fill in a container so that it's about to rehash
|
||||
template <typename T> void rehash_prep(T& x)
|
||||
{
|
||||
test::random_values<T> values;
|
||||
insert_test_base(unsigned int count = 5)
|
||||
: values(count, test::limited_range)
|
||||
{
|
||||
using namespace std;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
|
||||
|
||||
x.max_load_factor(0.25);
|
||||
size_type bucket_count = x.bucket_count();
|
||||
size_type initial_elements = static_cast<size_type>(
|
||||
ceil((double)bucket_count * (double)x.max_load_factor()) - 1);
|
||||
test::random_values<T> v(initial_elements);
|
||||
x.insert(v.begin(), v.end());
|
||||
BOOST_TEST(bucket_count == x.bucket_count());
|
||||
}
|
||||
|
||||
// Overload to generate inserters that need type information.
|
||||
|
||||
template <typename Inserter, typename T>
|
||||
Inserter generate(Inserter inserter, T&)
|
||||
{
|
||||
return inserter;
|
||||
}
|
||||
|
||||
// Get the iterator returned from an insert/emplace.
|
||||
|
||||
template <typename T> T get_iterator(T const& x) { return x; }
|
||||
|
||||
template <typename T> T get_iterator(std::pair<T, bool> const& x)
|
||||
{
|
||||
return x.first;
|
||||
}
|
||||
|
||||
// Generic insert exception test for typical single element inserts..
|
||||
|
||||
template <typename T, typename Inserter, typename Values>
|
||||
void insert_exception_test_impl(T x, Inserter insert, Values const& v)
|
||||
{
|
||||
test::strong<T> strong;
|
||||
|
||||
test::ordered<T> tracker;
|
||||
tracker.insert(x.begin(), x.end());
|
||||
|
||||
try {
|
||||
ENABLE_EXCEPTIONS;
|
||||
|
||||
for (typename Values::const_iterator it = v.begin(); it != v.end();
|
||||
++it) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
insert(x, it);
|
||||
}
|
||||
} catch (...) {
|
||||
test::check_equivalent_keys(x);
|
||||
insert.exception_check(x, strong);
|
||||
throw;
|
||||
}
|
||||
|
||||
typedef T data_type;
|
||||
typedef test::strong<T> strong_type;
|
||||
test::check_equivalent_keys(x);
|
||||
insert.track(tracker, v.begin(), v.end());
|
||||
tracker.compare(x);
|
||||
}
|
||||
|
||||
data_type init() const { return T(); }
|
||||
// Simple insert exception test
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||
T const& x, strong_type const& strong) const
|
||||
template <typename T, typename Inserter>
|
||||
void insert_exception_test(T*, Inserter insert, test::random_generator gen)
|
||||
{
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
test::random_values<T> v(10, gen);
|
||||
T x;
|
||||
|
||||
EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v));
|
||||
}
|
||||
}
|
||||
|
||||
// Insert into a container which is about to hit its max load, so that it
|
||||
// rehashes.
|
||||
|
||||
template <typename T, typename Inserter>
|
||||
void insert_rehash_exception_test(
|
||||
T*, Inserter insert, test::random_generator gen)
|
||||
{
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
T x;
|
||||
rehash_prep(x);
|
||||
|
||||
test::random_values<T> v2(5, gen);
|
||||
EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v2));
|
||||
}
|
||||
}
|
||||
|
||||
// Various methods for inserting a single element
|
||||
|
||||
struct inserter_base
|
||||
{
|
||||
template <typename T> void exception_check(T& x, test::strong<T>& strong)
|
||||
{
|
||||
std::string scope(test::scope);
|
||||
|
||||
if (scope.find("hash::operator()") == std::string::npos)
|
||||
strong.test(x, test::detail::tracker.count_allocations);
|
||||
}
|
||||
|
||||
template <typename T, typename Iterator>
|
||||
void track(T& tracker, Iterator begin, Iterator end)
|
||||
{
|
||||
tracker.insert(begin, end);
|
||||
}
|
||||
};
|
||||
|
||||
struct insert_lvalue_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.insert(*it);
|
||||
}
|
||||
} insert_lvalue;
|
||||
|
||||
struct insert_lvalue_begin_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.insert(x.begin(), *it);
|
||||
}
|
||||
} insert_lvalue_begin;
|
||||
|
||||
struct insert_lvalue_end_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.insert(x.end(), *it);
|
||||
}
|
||||
} insert_lvalue_end;
|
||||
|
||||
struct insert_lvalue_pos_type
|
||||
{
|
||||
template <typename T> struct impl : inserter_base
|
||||
{
|
||||
typename T::iterator pos;
|
||||
|
||||
impl(T& x) : pos(x.begin()) {}
|
||||
|
||||
template <typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
pos = get_iterator(x.insert(pos, *it));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> friend impl<T> generate(insert_lvalue_pos_type, T& x)
|
||||
{
|
||||
return impl<T>(x);
|
||||
}
|
||||
} insert_lvalue_pos;
|
||||
|
||||
struct insert_single_item_range_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.insert(it, test::next(it));
|
||||
}
|
||||
} insert_single_item_range;
|
||||
|
||||
struct emplace_lvalue_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.emplace(*it);
|
||||
}
|
||||
} emplace_lvalue;
|
||||
|
||||
struct emplace_lvalue_begin_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.emplace_hint(x.begin(), *it);
|
||||
}
|
||||
} emplace_lvalue_begin;
|
||||
|
||||
struct emplace_lvalue_end_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.emplace_hint(x.end(), *it);
|
||||
}
|
||||
} emplace_lvalue_end;
|
||||
|
||||
struct emplace_lvalue_pos_type
|
||||
{
|
||||
template <typename T> struct impl : inserter_base
|
||||
{
|
||||
typename T::iterator pos;
|
||||
|
||||
impl(T& x) : pos(x.begin()) {}
|
||||
|
||||
template <typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
pos = get_iterator(x.emplace_hint(pos, *it));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> friend impl<T> generate(emplace_lvalue_pos_type, T& x)
|
||||
{
|
||||
return impl<T>(x);
|
||||
}
|
||||
} emplace_lvalue_pos;
|
||||
|
||||
// Run the exception tests in various combinations.
|
||||
|
||||
test_set* test_set_;
|
||||
test_multiset* test_multiset_;
|
||||
test_map* test_map_;
|
||||
test_multimap* test_multimap_;
|
||||
|
||||
using test::default_generator;
|
||||
using test::limited_range;
|
||||
using test::generate_collisions;
|
||||
|
||||
// clang-format off
|
||||
UNORDERED_TEST(insert_exception_test,
|
||||
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
|
||||
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
|
||||
(insert_lvalue_pos)(insert_single_item_range)
|
||||
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
|
||||
(emplace_lvalue_pos)
|
||||
)
|
||||
((default_generator)(limited_range)(generate_collisions))
|
||||
)
|
||||
|
||||
UNORDERED_TEST(insert_rehash_exception_test,
|
||||
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
|
||||
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
|
||||
(insert_lvalue_pos)(insert_single_item_range)
|
||||
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
|
||||
(emplace_lvalue_pos)
|
||||
)
|
||||
((default_generator)(limited_range)(generate_collisions))
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
// Repeat insert tests with pairs
|
||||
|
||||
struct pair_emplace_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(it->first), boost::make_tuple(it->second));
|
||||
}
|
||||
} pair_emplace;
|
||||
|
||||
struct pair_emplace2_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.emplace_hint(x.begin(), boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(it->first),
|
||||
boost::make_tuple(it->second.tag1_, it->second.tag2_));
|
||||
}
|
||||
} pair_emplace2;
|
||||
|
||||
test_pair_set* test_pair_set_;
|
||||
test_pair_multiset* test_pair_multiset_;
|
||||
|
||||
// clang-format off
|
||||
UNORDERED_TEST(insert_exception_test,
|
||||
((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
|
||||
((pair_emplace)(pair_emplace2))
|
||||
((default_generator)(limited_range)(generate_collisions))
|
||||
)
|
||||
UNORDERED_TEST(insert_rehash_exception_test,
|
||||
((test_pair_set_)(test_pair_multiset_)(test_map_)(test_multimap_))
|
||||
((pair_emplace)(pair_emplace2))
|
||||
((default_generator)(limited_range)(generate_collisions))
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
// Test inserting using operator[]
|
||||
|
||||
struct try_emplace_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.try_emplace(it->first, it->second);
|
||||
}
|
||||
} try_emplace;
|
||||
|
||||
struct try_emplace2_type : inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.try_emplace(it->first, it->second.tag1_, it->second.tag2_);
|
||||
}
|
||||
} try_emplace2;
|
||||
|
||||
struct map_inserter_base
|
||||
{
|
||||
template <typename T> void exception_check(T& x, test::strong<T>& strong)
|
||||
{
|
||||
std::string scope(test::scope);
|
||||
|
||||
if (scope.find("hash::operator()") == std::string::npos &&
|
||||
scope.find("::operator=") == std::string::npos)
|
||||
strong.test(x, test::detail::tracker.count_allocations);
|
||||
}
|
||||
|
||||
template <typename T, typename Iterator>
|
||||
void track(T& tracker, Iterator begin, Iterator end)
|
||||
{
|
||||
for (; begin != end; ++begin) {
|
||||
tracker[begin->first] = begin->second;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct map_insert_operator_type : map_inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x[it->first] = it->second;
|
||||
}
|
||||
} map_insert_operator;
|
||||
|
||||
struct map_insert_or_assign_type : map_inserter_base
|
||||
{
|
||||
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
|
||||
{
|
||||
x.insert_or_assign(it->first, it->second);
|
||||
}
|
||||
} map_insert_or_assign;
|
||||
|
||||
// clang-format off
|
||||
UNORDERED_TEST(insert_exception_test,
|
||||
((test_map_))
|
||||
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
|
||||
((default_generator)(limited_range)(generate_collisions))
|
||||
)
|
||||
UNORDERED_TEST(insert_rehash_exception_test,
|
||||
((test_map_))
|
||||
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
|
||||
((default_generator)(limited_range)(generate_collisions))
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
// Range insert tests
|
||||
|
||||
template <typename T, typename Values>
|
||||
void insert_range_exception_test_impl(T x, Values const& v)
|
||||
{
|
||||
test::ordered<T> tracker;
|
||||
tracker.insert(x.begin(), x.end());
|
||||
|
||||
try {
|
||||
ENABLE_EXCEPTIONS;
|
||||
x.insert(v.begin(), v.end());
|
||||
} catch (...) {
|
||||
test::check_equivalent_keys(x);
|
||||
throw;
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
|
||||
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
test::check_equivalent_keys(x);
|
||||
tracker.insert(v.begin(), v.end());
|
||||
tracker.compare(x);
|
||||
}
|
||||
|
||||
template <class T> struct emplace_test1 : public insert_test_base<T>
|
||||
template <typename T>
|
||||
void insert_range_exception_test(T*, test::random_generator gen)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(),
|
||||
end = this->values.end();
|
||||
it != end; ++it) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x.emplace(*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <class T> struct insert_test1 : public insert_test_base<T>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(),
|
||||
end = this->values.end();
|
||||
it != end; ++it) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x.insert(*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test2 : public insert_test_base<T>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(),
|
||||
end = this->values.end();
|
||||
it != end; ++it) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x.insert(x.begin(), *it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test3 : public insert_test_base<T>
|
||||
{
|
||||
void run(T& x) const { x.insert(this->values.begin(), this->values.end()); }
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
|
||||
{
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test4 : public insert_test_base<T>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(),
|
||||
end = this->values.end();
|
||||
it != end; ++it) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x.insert(it, test::next(it));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test_rehash1 : public insert_test_base<T>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
insert_test_rehash1() : insert_test_base<T>(1000) {}
|
||||
|
||||
T init() const
|
||||
{
|
||||
using namespace std;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
test::random_values<T> v(10, gen);
|
||||
T x;
|
||||
x.max_load_factor(0.25);
|
||||
// TODO: This doesn't really work is bucket_count is 0
|
||||
size_type bucket_count = x.bucket_count();
|
||||
size_type initial_elements = static_cast<size_type>(
|
||||
ceil((double)bucket_count * (double)x.max_load_factor()) - 1);
|
||||
BOOST_TEST(initial_elements < this->values.size());
|
||||
x.insert(this->values.begin(),
|
||||
test::next(this->values.begin(), initial_elements));
|
||||
BOOST_TEST(bucket_count == x.bucket_count());
|
||||
return x;
|
||||
|
||||
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v));
|
||||
}
|
||||
}
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
|
||||
int count = 0;
|
||||
BOOST_DEDUCED_TYPENAME T::const_iterator pos = x.cbegin();
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = test::next(this->values.begin(), x.size()),
|
||||
end = this->values.end();
|
||||
it != end && count < 10; ++it, ++count) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
pos = x.insert(pos, *it);
|
||||
}
|
||||
|
||||
// This isn't actually a failure, but it means the test isn't doing its
|
||||
// job.
|
||||
BOOST_TEST(x.bucket_count() != bucket_count);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test_rehash2 : public insert_test_rehash1<T>
|
||||
template <typename T>
|
||||
void insert_range_rehash_exception_test(T*, test::random_generator gen)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
|
||||
int count = 0;
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = test::next(this->values.begin(), x.size()),
|
||||
end = this->values.end();
|
||||
it != end && count < 10; ++it, ++count) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x.insert(*it);
|
||||
}
|
||||
|
||||
// This isn't actually a failure, but it means the test isn't doing its
|
||||
// job.
|
||||
BOOST_TEST(x.bucket_count() != bucket_count);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct insert_test_rehash3 : public insert_test_base<T>
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::size_type mutable rehash_bucket_count,
|
||||
original_bucket_count;
|
||||
|
||||
insert_test_rehash3() : insert_test_base<T>(1000) {}
|
||||
|
||||
T init() const
|
||||
{
|
||||
using namespace std;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
T x;
|
||||
x.max_load_factor(0.25);
|
||||
rehash_prep(x);
|
||||
|
||||
original_bucket_count = x.bucket_count();
|
||||
rehash_bucket_count =
|
||||
static_cast<size_type>(ceil(
|
||||
(double)original_bucket_count * (double)x.max_load_factor())) -
|
||||
1;
|
||||
|
||||
size_type initial_elements =
|
||||
rehash_bucket_count > 5 ? rehash_bucket_count - 5 : 1;
|
||||
|
||||
BOOST_TEST(initial_elements < this->values.size());
|
||||
x.insert(this->values.begin(),
|
||||
test::next(this->values.begin(), initial_elements));
|
||||
BOOST_TEST(original_bucket_count == x.bucket_count());
|
||||
return x;
|
||||
test::random_values<T> v2(5, gen);
|
||||
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v2));
|
||||
}
|
||||
}
|
||||
|
||||
void run(T& x) const
|
||||
{
|
||||
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
|
||||
// clang-format off
|
||||
UNORDERED_TEST(insert_range_exception_test,
|
||||
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
|
||||
((default_generator)(limited_range)(generate_collisions))
|
||||
)
|
||||
|
||||
x.insert(test::next(this->values.begin(), x.size()),
|
||||
test::next(this->values.begin(), x.size() + 20));
|
||||
|
||||
// This isn't actually a failure, but it means the test isn't doing its
|
||||
// job.
|
||||
BOOST_TEST(x.bucket_count() != bucket_count);
|
||||
}
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
|
||||
{
|
||||
if (x.size() < rehash_bucket_count) {
|
||||
// BOOST_TEST(x.bucket_count() == original_bucket_count);
|
||||
}
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
#define BASIC_TESTS \
|
||||
(insert_test1)(insert_test2)(insert_test3)(insert_test4)( \
|
||||
insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
|
||||
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#define ALL_TESTS (emplace_test1) BASIC_TESTS
|
||||
#else
|
||||
#define ALL_TESTS BASIC_TESTS
|
||||
#endif
|
||||
|
||||
EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
|
||||
|
||||
template <class T> struct pair_emplace_test1 : public insert_test_base<T>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(),
|
||||
end = this->values.end();
|
||||
it != end; ++it) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(it->first), boost::make_tuple(it->second));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct pair_emplace_test2 : public insert_test_base<T>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(),
|
||||
end = this->values.end();
|
||||
it != end; ++it) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(it->first),
|
||||
boost::make_tuple(it->second.tag1_, it->second.tag2_));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((pair_emplace_test1)(pair_emplace_test2), CONTAINER_PAIR_SEQ)
|
||||
|
||||
template <class T> struct index_insert_test1 : public insert_test_base<T>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
|
||||
|
||||
void run(T& x, strong_type& strong) const
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
|
||||
it = this->values.begin(),
|
||||
end = this->values.end();
|
||||
it != end; ++it) {
|
||||
strong.store(x, test::detail::tracker.count_allocations);
|
||||
x[it->first];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((index_insert_test1), (test_map))
|
||||
UNORDERED_TEST(insert_range_rehash_exception_test,
|
||||
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
|
||||
((default_generator)(limited_range)(generate_collisions))
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
RUN_TESTS()
|
||||
|
103
test/exception/merge_exception_tests.cpp
Normal file
103
test/exception/merge_exception_tests.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include "../helpers/exception_test.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/metafunctions.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "./containers.hpp"
|
||||
|
||||
template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y)
|
||||
{
|
||||
std::size_t size = x.size() + y.size();
|
||||
|
||||
try {
|
||||
ENABLE_EXCEPTIONS;
|
||||
x.merge(y);
|
||||
} catch (...) {
|
||||
test::check_equivalent_keys(x);
|
||||
test::check_equivalent_keys(y);
|
||||
throw;
|
||||
}
|
||||
|
||||
// Not a full check, just want to make sure the merge completed.
|
||||
BOOST_TEST(size == x.size() + y.size());
|
||||
if (y.size()) {
|
||||
BOOST_TEST(test::has_unique_keys<T1>::value);
|
||||
for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
|
||||
BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
|
||||
}
|
||||
}
|
||||
test::check_equivalent_keys(x);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12,
|
||||
test::random_generator gen1, test::random_generator gen2)
|
||||
{
|
||||
std::size_t count1 = count12 / 256;
|
||||
std::size_t count2 = count12 % 256;
|
||||
int tag1 = tag12 / 256;
|
||||
int tag2 = tag12 % 256;
|
||||
test::random_values<T1> v1(count1, gen1);
|
||||
test::random_values<T2> v2(count2, gen2);
|
||||
T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1),
|
||||
test::exception::equal_to(tag1));
|
||||
T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2),
|
||||
test::exception::equal_to(tag2));
|
||||
|
||||
EXCEPTION_LOOP(merge_exception_test(x, y))
|
||||
}
|
||||
|
||||
boost::unordered_set<test::exception::object, test::exception::hash,
|
||||
test::exception::equal_to,
|
||||
test::exception::allocator<test::exception::object> >* test_set_;
|
||||
boost::unordered_multiset<test::exception::object, test::exception::hash,
|
||||
test::exception::equal_to,
|
||||
test::exception::allocator<test::exception::object> >* test_multiset_;
|
||||
boost::unordered_map<test::exception::object, test::exception::object,
|
||||
test::exception::hash, test::exception::equal_to,
|
||||
test::exception::allocator2<test::exception::object> >* test_map_;
|
||||
boost::unordered_multimap<test::exception::object, test::exception::object,
|
||||
test::exception::hash, test::exception::equal_to,
|
||||
test::exception::allocator2<test::exception::object> >* test_multimap_;
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
using test::limited_range;
|
||||
|
||||
// clang-format off
|
||||
UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
|
||||
((test_set_)(test_multiset_))
|
||||
((test_set_)(test_multiset_))
|
||||
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
|
||||
((0x0000)(0x0001)(0x0102))
|
||||
((default_generator)(limited_range))
|
||||
((default_generator)(limited_range))
|
||||
)
|
||||
UNORDERED_MULTI_TEST(map_merge, merge_exception_test,
|
||||
((test_map_)(test_multimap_))
|
||||
((test_map_)(test_multimap_))
|
||||
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
|
||||
((0x0101)(0x0200)(0x0201))
|
||||
((default_generator)(limited_range))
|
||||
((default_generator)(limited_range))
|
||||
)
|
||||
// Run fewer generate_collisions tests, as they're slow.
|
||||
UNORDERED_MULTI_TEST(set_merge_collisions, merge_exception_test,
|
||||
((test_set_)(test_multiset_))
|
||||
((test_set_)(test_multiset_))
|
||||
((0x0a0a))
|
||||
((0x0202)(0x0100)(0x0201))
|
||||
((generate_collisions))
|
||||
((generate_collisions))
|
||||
)
|
||||
UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
|
||||
((test_map_)(test_multimap_))
|
||||
((test_map_)(test_multimap_))
|
||||
((0x0a0a))
|
||||
((0x0000)(0x0002)(0x0102))
|
||||
((generate_collisions))
|
||||
((generate_collisions))
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
RUN_TESTS_QUIET()
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include <iostream>
|
||||
#include "../helpers/tracker.hpp"
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning( \
|
||||
@ -42,7 +42,12 @@ template <class T> struct move_assign_base : public test::exception_base
|
||||
T y1 = y;
|
||||
disable_exceptions.release();
|
||||
x1 = boost::move(y1);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x1, y_values);
|
||||
test::check_equivalent_keys(x1);
|
||||
}
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
|
||||
{
|
||||
test::check_equivalent_keys(x1);
|
||||
@ -64,8 +69,8 @@ template <class T> struct move_assign_values : move_assign_base<T>
|
||||
int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
|
||||
: move_assign_base<T>(tag1, tag2, mlf1, mlf2)
|
||||
{
|
||||
this->x_values.fill(count1);
|
||||
this->y_values.fill(count2);
|
||||
this->x_values.fill(count1, test::limited_range);
|
||||
this->y_values.fill(count2, test::limited_range);
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
this->y.insert(this->y_values.begin(), this->y_values.end());
|
||||
}
|
||||
@ -105,10 +110,10 @@ template <class T> struct equivalent_test1 : move_assign_base<T>
|
||||
{
|
||||
equivalent_test1() : move_assign_base<T>(0, 0)
|
||||
{
|
||||
test::random_values<T> x_values2(10);
|
||||
test::random_values<T> x_values2(10, test::limited_range);
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
this->x_values.insert(x_values2.begin(), x_values2.end());
|
||||
test::random_values<T> y_values2(10);
|
||||
test::random_values<T> y_values2(10, test::limited_range);
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->y_values.insert(y_values2.begin(), y_values2.end());
|
||||
this->x.insert(this->x_values.begin(), this->x_values.end());
|
||||
|
@ -8,10 +8,9 @@
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/strong.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include <string>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
test::seed_t initialize_seed(3298597);
|
||||
|
||||
template <class T> struct rehash_test_base : public test::exception_base
|
||||
@ -19,7 +18,7 @@ template <class T> struct rehash_test_base : public test::exception_base
|
||||
test::random_values<T> values;
|
||||
unsigned int n;
|
||||
rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
|
||||
: values(count), n(n_)
|
||||
: values(count, test::limited_range), n(n_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -49,34 +48,82 @@ template <class T> struct rehash_test_base : public test::exception_base
|
||||
template <class T> struct rehash_test0 : rehash_test_base<T>
|
||||
{
|
||||
rehash_test0() : rehash_test_base<T>(0) {}
|
||||
void run(T& x) const { x.rehash(0); }
|
||||
void run(T& x) const
|
||||
{
|
||||
x.rehash(0);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct rehash_test1 : rehash_test_base<T>
|
||||
{
|
||||
rehash_test1() : rehash_test_base<T>(0) {}
|
||||
void run(T& x) const { x.rehash(200); }
|
||||
void run(T& x) const
|
||||
{
|
||||
x.rehash(200);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct rehash_test2 : rehash_test_base<T>
|
||||
{
|
||||
rehash_test2() : rehash_test_base<T>(0, 200) {}
|
||||
void run(T& x) const { x.rehash(0); }
|
||||
void run(T& x) const
|
||||
{
|
||||
x.rehash(0);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct rehash_test3 : rehash_test_base<T>
|
||||
{
|
||||
rehash_test3() : rehash_test_base<T>(10, 0) {}
|
||||
void run(T& x) const { x.rehash(200); }
|
||||
void run(T& x) const
|
||||
{
|
||||
x.rehash(200);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct rehash_test4 : rehash_test_base<T>
|
||||
{
|
||||
rehash_test4() : rehash_test_base<T>(10, 200) {}
|
||||
void run(T& x) const { x.rehash(0); }
|
||||
void run(T& x) const
|
||||
{
|
||||
x.rehash(0);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS(
|
||||
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4),
|
||||
template <class T> struct rehash_test5 : rehash_test_base<T>
|
||||
{
|
||||
rehash_test5() : rehash_test_base<T>(200, 10) {}
|
||||
void run(T& x) const
|
||||
{
|
||||
x.rehash(0);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
};
|
||||
|
||||
EXCEPTION_TESTS((rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(
|
||||
rehash_test4)(rehash_test5),
|
||||
CONTAINER_SEQ)
|
||||
RUN_TESTS()
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable : 4512) // assignment operator could not be generated
|
||||
@ -17,11 +18,22 @@ test::seed_t initialize_seed(9387);
|
||||
template <class T> struct self_swap_base : public test::exception_base
|
||||
{
|
||||
test::random_values<T> values;
|
||||
self_swap_base(std::size_t count = 0) : values(count) {}
|
||||
self_swap_base(std::size_t count = 0) : values(count, test::limited_range)
|
||||
{
|
||||
}
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(values.begin(), values.end()); }
|
||||
void run(T& x) const { x.swap(x); }
|
||||
|
||||
void run(T& x) const
|
||||
{
|
||||
x.swap(x);
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(x, this->values);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
|
||||
{
|
||||
std::string scope(test::scope);
|
||||
@ -55,7 +67,8 @@ template <class T> struct swap_base : public test::exception_base
|
||||
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
|
||||
|
||||
swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
|
||||
: x_values(count1), y_values(count2),
|
||||
: x_values(count1, test::limited_range),
|
||||
y_values(count2, test::limited_range),
|
||||
initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
|
||||
key_equal(tag1), allocator_type(tag1)),
|
||||
initial_y(
|
||||
@ -82,7 +95,14 @@ template <class T> struct swap_base : public test::exception_base
|
||||
d.x.swap(d.y);
|
||||
} catch (std::runtime_error) {
|
||||
}
|
||||
|
||||
DISABLE_EXCEPTIONS;
|
||||
test::check_container(d.x, this->y_values);
|
||||
test::check_equivalent_keys(d.x);
|
||||
test::check_container(d.y, this->x_values);
|
||||
test::check_equivalent_keys(d.y);
|
||||
}
|
||||
|
||||
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const
|
||||
{
|
||||
std::string scope(test::scope);
|
||||
|
@ -7,7 +7,6 @@
|
||||
#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace test {
|
||||
struct object_count
|
||||
|
@ -241,8 +241,10 @@ template <class Test> void exception_safety(Test const& f, char const* /*name*/)
|
||||
|
||||
iteration = 0;
|
||||
bool success = false;
|
||||
unsigned int failure_count = 0;
|
||||
char const* error_msg = 0;
|
||||
do {
|
||||
int error_count = boost::detail::test_errors();
|
||||
++iteration;
|
||||
count = 0;
|
||||
|
||||
@ -252,19 +254,98 @@ template <class Test> void exception_safety(Test const& f, char const* /*name*/)
|
||||
} catch (test_failure) {
|
||||
error_msg = "test_failure caught.";
|
||||
break;
|
||||
} catch (test_exception) {
|
||||
continue;
|
||||
} catch (test_exception e) {
|
||||
if (error_count != boost::detail::test_errors()) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM
|
||||
<< "Iteration: " << iteration
|
||||
<< " Error found for epoint: " << e.name << std::endl;
|
||||
}
|
||||
} catch (...) {
|
||||
error_msg = "Unexpected exception.";
|
||||
break;
|
||||
}
|
||||
} while (!success);
|
||||
|
||||
if (error_count != boost::detail::test_errors()) {
|
||||
++failure_count;
|
||||
}
|
||||
} while (!success && failure_count < 5);
|
||||
|
||||
if (error_msg) {
|
||||
BOOST_ERROR(error_msg);
|
||||
}
|
||||
runner.end();
|
||||
}
|
||||
|
||||
//
|
||||
// An alternative way to run exception tests.
|
||||
// See merge_exception_tests.cpp for an example.
|
||||
|
||||
struct exception_looper
|
||||
{
|
||||
bool success;
|
||||
unsigned int failure_count;
|
||||
char const* error_msg;
|
||||
int error_count;
|
||||
|
||||
exception_looper() : success(false), failure_count(0), error_msg(0) {}
|
||||
|
||||
void start() { iteration = 0; }
|
||||
|
||||
bool loop_condition() const
|
||||
{
|
||||
return !error_msg && !success && failure_count < 5;
|
||||
}
|
||||
|
||||
void start_iteration()
|
||||
{
|
||||
error_count = boost::detail::test_errors();
|
||||
++iteration;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
void successful_run() { success = true; }
|
||||
|
||||
void test_failure_caught(test_failure const&)
|
||||
{
|
||||
error_msg = "test_failure caught.";
|
||||
}
|
||||
|
||||
void test_exception_caught(test_exception const& e)
|
||||
{
|
||||
if (error_count != boost::detail::test_errors()) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM
|
||||
<< "Iteration: " << iteration
|
||||
<< " Error found for epoint: " << e.name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void unexpected_exception_caught() { error_msg = "Unexpected exception."; }
|
||||
|
||||
void end()
|
||||
{
|
||||
if (error_msg) {
|
||||
BOOST_ERROR(error_msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define EXCEPTION_LOOP(op) \
|
||||
test::lightweight::exception_looper looper; \
|
||||
looper.start(); \
|
||||
while (looper.loop_condition()) { \
|
||||
looper.start_iteration(); \
|
||||
try { \
|
||||
op; \
|
||||
looper.successful_run(); \
|
||||
} catch (test::lightweight::test_failure e) { \
|
||||
looper.test_failure_caught(e); \
|
||||
} catch (test::lightweight::test_exception e) { \
|
||||
looper.test_exception_caught(e); \
|
||||
} catch (...) { \
|
||||
looper.unexpected_exception_caught(); \
|
||||
} \
|
||||
} \
|
||||
looper.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,20 +63,28 @@ template <class X> void check_equivalent_keys(X const& x1)
|
||||
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);
|
||||
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit)
|
||||
continue;
|
||||
if (lit == lend)
|
||||
|
||||
unsigned int count_checked = 0;
|
||||
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
|
||||
++count_checked;
|
||||
}
|
||||
|
||||
if (lit == lend) {
|
||||
BOOST_ERROR("Unable to find element with a local_iterator");
|
||||
unsigned int count2 = 0;
|
||||
for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
|
||||
++count2;
|
||||
if (count != count2)
|
||||
BOOST_ERROR("Element count doesn't match local_iterator.");
|
||||
for (; lit != lend; ++lit) {
|
||||
if (eq(get_key<X>(*lit), key)) {
|
||||
BOOST_ERROR("Non-adjacent element with equivalent key "
|
||||
"in bucket.");
|
||||
break;
|
||||
std::cerr << "Checked: " << count_checked << " elements"
|
||||
<< std::endl;
|
||||
} else {
|
||||
unsigned int count2 = 0;
|
||||
for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
|
||||
++count2;
|
||||
if (count != count2)
|
||||
BOOST_ERROR("Element count doesn't match local_iterator.");
|
||||
for (; lit != lend; ++lit) {
|
||||
if (eq(get_key<X>(*lit), key)) {
|
||||
BOOST_ERROR("Non-adjacent element with equivalent key "
|
||||
"in bucket.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -60,12 +60,16 @@ struct memory_tracker
|
||||
unsigned int count_allocators;
|
||||
unsigned int count_allocations;
|
||||
unsigned int count_constructions;
|
||||
bool tracking_constructions;
|
||||
|
||||
memory_tracker()
|
||||
: count_allocators(0), count_allocations(0), count_constructions(0)
|
||||
: count_allocators(0), count_allocations(0), count_constructions(0),
|
||||
tracking_constructions(true)
|
||||
{
|
||||
}
|
||||
|
||||
~memory_tracker() { BOOST_TEST(count_allocators == 0); }
|
||||
|
||||
void allocator_ref()
|
||||
{
|
||||
if (count_allocators == 0) {
|
||||
@ -131,14 +135,18 @@ struct memory_tracker
|
||||
|
||||
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
|
||||
{
|
||||
++count_constructions;
|
||||
if (tracking_constructions) {
|
||||
++count_constructions;
|
||||
}
|
||||
}
|
||||
|
||||
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
|
||||
{
|
||||
BOOST_TEST(count_constructions > 0);
|
||||
if (count_constructions > 0)
|
||||
--count_constructions;
|
||||
if (tracking_constructions) {
|
||||
BOOST_TEST(count_constructions > 0);
|
||||
if (count_constructions > 0)
|
||||
--count_constructions;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -153,6 +161,29 @@ namespace {
|
||||
test::detail::memory_tracker tracker;
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
struct disable_construction_tracking
|
||||
{
|
||||
bool old_value;
|
||||
|
||||
disable_construction_tracking()
|
||||
: old_value(detail::tracker.tracking_constructions)
|
||||
{
|
||||
test::detail::tracker.tracking_constructions = false;
|
||||
}
|
||||
|
||||
~disable_construction_tracking()
|
||||
{
|
||||
test::detail::tracker.tracking_constructions = old_value;
|
||||
}
|
||||
|
||||
private:
|
||||
disable_construction_tracking(disable_construction_tracking const&);
|
||||
disable_construction_tracking& operator=(
|
||||
disable_construction_tracking const&);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#define UNORDERED_AUTO_TEST(x) \
|
||||
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
|
||||
@ -17,7 +16,7 @@
|
||||
BOOST_PP_CAT(x, _type) \
|
||||
() : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
|
||||
{ \
|
||||
::test::test_list::add_test(this); \
|
||||
::test::get_state().add_test(this); \
|
||||
} \
|
||||
void run(); \
|
||||
}; \
|
||||
@ -27,12 +26,27 @@
|
||||
#define RUN_TESTS() \
|
||||
int main(int, char**) \
|
||||
{ \
|
||||
::test::write_compiler_info(); \
|
||||
::test::test_list::run_tests(); \
|
||||
BOOST_UNORDERED_TEST_COMPILER_INFO() \
|
||||
::test::get_state().run_tests(); \
|
||||
return boost::report_errors(); \
|
||||
}
|
||||
|
||||
#define RUN_TESTS_QUIET() \
|
||||
int main(int, char**) \
|
||||
{ \
|
||||
BOOST_UNORDERED_TEST_COMPILER_INFO() \
|
||||
::test::get_state().run_tests(true); \
|
||||
return boost::report_errors(); \
|
||||
}
|
||||
|
||||
#define UNORDERED_SUB_TEST(x) \
|
||||
for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \
|
||||
UNORDERED_SUB_TEST_VALUE; \
|
||||
UNORDERED_SUB_TEST_VALUE = \
|
||||
::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE))
|
||||
|
||||
namespace test {
|
||||
|
||||
struct registered_test_base
|
||||
{
|
||||
registered_test_base* next;
|
||||
@ -42,56 +56,95 @@ struct registered_test_base
|
||||
virtual ~registered_test_base() {}
|
||||
};
|
||||
|
||||
namespace test_list {
|
||||
static inline registered_test_base*& first()
|
||||
struct state
|
||||
{
|
||||
static registered_test_base* ptr = 0;
|
||||
return ptr;
|
||||
}
|
||||
bool is_quiet;
|
||||
registered_test_base* first_test;
|
||||
registered_test_base* last_test;
|
||||
|
||||
static inline registered_test_base*& last()
|
||||
{
|
||||
static registered_test_base* ptr = 0;
|
||||
return ptr;
|
||||
}
|
||||
state() : is_quiet(false), first_test(0), last_test(0) {}
|
||||
|
||||
static inline void add_test(registered_test_base* test)
|
||||
{
|
||||
if (last()) {
|
||||
last()->next = test;
|
||||
} else {
|
||||
first() = test;
|
||||
void add_test(registered_test_base* test)
|
||||
{
|
||||
if (last_test) {
|
||||
last_test->next = test;
|
||||
} else {
|
||||
first_test = test;
|
||||
}
|
||||
last_test = test;
|
||||
}
|
||||
|
||||
last() = test;
|
||||
}
|
||||
void run_tests(bool quiet = false)
|
||||
{
|
||||
is_quiet = quiet;
|
||||
|
||||
static inline void run_tests()
|
||||
{
|
||||
for (registered_test_base* i = first(); i; i = i->next) {
|
||||
std::cout << "Running " << i->name << "\n" << std::flush;
|
||||
i->run();
|
||||
std::cerr << std::flush;
|
||||
std::cout << std::flush;
|
||||
for (registered_test_base* i = first_test; i; i = i->next) {
|
||||
int error_count = boost::detail::test_errors();
|
||||
if (!quiet) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Running " << i->name << "\n"
|
||||
<< std::flush;
|
||||
}
|
||||
i->run();
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::flush;
|
||||
if (quiet && error_count != boost::detail::test_errors()) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in: " << i->name
|
||||
<< "\n"
|
||||
<< std::flush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int start_sub_test(char const* name)
|
||||
{
|
||||
if (!is_quiet) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Sub-test: " << name << "\n"
|
||||
<< std::flush;
|
||||
}
|
||||
// Add one because it's used as a loop condition.
|
||||
return boost::detail::test_errors() + 1;
|
||||
}
|
||||
|
||||
int end_sub_test(char const* name, int value)
|
||||
{
|
||||
if (is_quiet && value != boost::detail::test_errors() + 1) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in sub-test: " << name
|
||||
<< "\n"
|
||||
<< std::flush;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Get the currnet translation unit's test state.
|
||||
static inline state& get_state()
|
||||
{
|
||||
static state instance;
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
inline void write_compiler_info()
|
||||
{
|
||||
#if defined(BOOST_GCC_CXX11)
|
||||
char const* cpp11 = "true";
|
||||
#if defined(__cplusplus)
|
||||
#define BOOST_UNORDERED_CPLUSPLUS __cplusplus
|
||||
#else
|
||||
char const* cpp11 = "false";
|
||||
#define BOOST_UNORDERED_CPLUSPLUS "(not defined)"
|
||||
#endif
|
||||
|
||||
std::cout << "Compiler: " << BOOST_COMPILER << "\n"
|
||||
<< "Library: " << BOOST_STDLIB << "\n"
|
||||
<< "C++11: " << cpp11 << "\n"
|
||||
<< "\n"
|
||||
<< std::flush;
|
||||
}
|
||||
}
|
||||
#define BOOST_UNORDERED_TEST_COMPILER_INFO() \
|
||||
{ \
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
|
||||
<< "Compiler: " << BOOST_COMPILER << "\n" \
|
||||
<< "Library: " << BOOST_STDLIB << "\n" \
|
||||
<< "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \
|
||||
<< "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \
|
||||
<< BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
|
||||
<< "BOOST_UNORDERED_EMPLACE_LIMIT: " \
|
||||
<< BOOST_UNORDERED_EMPLACE_LIMIT << "\n" \
|
||||
<< "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \
|
||||
<< BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \
|
||||
<< "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
|
||||
<< BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \
|
||||
<< std::flush; \
|
||||
}
|
||||
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/seq/fold_left.hpp>
|
||||
@ -122,4 +175,31 @@ inline void write_compiler_info()
|
||||
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
|
||||
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
|
||||
|
||||
#define UNORDERED_MULTI_TEST(name, impl, parameters) \
|
||||
UNORDERED_MULTI_TEST_REPEAT(name, impl, 1, parameters)
|
||||
|
||||
#define UNORDERED_MULTI_TEST_REPEAT(name, impl, n, parameters) \
|
||||
UNORDERED_AUTO_TEST(name) \
|
||||
{ \
|
||||
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
|
||||
UNORDERED_MULTI_TEST_OP, ((impl))((n))parameters) \
|
||||
}
|
||||
|
||||
#define UNORDERED_MULTI_TEST_OP(r, product) \
|
||||
UNORDERED_MULTI_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
|
||||
BOOST_PP_SEQ_ELEM(1, product), \
|
||||
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
|
||||
|
||||
// Need to wrap UNORDERED_SUB_TEST in a block to avoid an msvc bug.
|
||||
// https://support.microsoft.com/en-gb/help/315481/bug-too-many-unnested-loops-incorrectly-causes-a-c1061-compiler-error-in-visual-c
|
||||
#define UNORDERED_MULTI_TEST_OP2(name, n, params) \
|
||||
{ \
|
||||
UNORDERED_SUB_TEST(BOOST_PP_STRINGIZE( \
|
||||
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params))) \
|
||||
{ \
|
||||
for (int i = 0; i < n; ++i) \
|
||||
name BOOST_PP_SEQ_TO_TUPLE(params); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -10,10 +10,11 @@
|
||||
|
||||
#include "../helpers/count.hpp"
|
||||
#include "../helpers/fwd.hpp"
|
||||
#include "../helpers/generators.hpp"
|
||||
#include "../helpers/memory.hpp"
|
||||
#include "./fwd.hpp"
|
||||
#include <boost/limits.hpp>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <new>
|
||||
|
||||
namespace test {
|
||||
@ -225,6 +226,55 @@ class hash
|
||||
}
|
||||
};
|
||||
|
||||
class less
|
||||
{
|
||||
int tag_;
|
||||
|
||||
public:
|
||||
less(int t = 0) : tag_(t) {}
|
||||
|
||||
less(less const& x) : tag_(x.tag_) {}
|
||||
|
||||
bool operator()(object const& x1, object const& x2) const
|
||||
{
|
||||
return less_impl(x1, x2);
|
||||
}
|
||||
|
||||
bool operator()(std::pair<object, object> const& x1,
|
||||
std::pair<object, object> const& x2) const
|
||||
{
|
||||
if (less_impl(x1.first, x2.first)) {
|
||||
return true;
|
||||
}
|
||||
if (!less_impl(x1.first, x2.first)) {
|
||||
return false;
|
||||
}
|
||||
return less_impl(x1.second, x2.second);
|
||||
}
|
||||
|
||||
bool less_impl(object const& x1, object const& x2) const
|
||||
{
|
||||
switch (tag_) {
|
||||
case 1:
|
||||
return x1.tag1_ < x2.tag1_;
|
||||
case 2:
|
||||
return x1.tag2_ < x2.tag2_;
|
||||
default:
|
||||
return x1 < x2;
|
||||
}
|
||||
}
|
||||
|
||||
friend bool operator==(less const& x1, less const& x2)
|
||||
{
|
||||
return x1.tag_ == x2.tag_;
|
||||
}
|
||||
|
||||
friend bool operator!=(less const& x1, less const& x2)
|
||||
{
|
||||
return x1.tag_ != x2.tag_;
|
||||
}
|
||||
};
|
||||
|
||||
class equal_to
|
||||
{
|
||||
int tag_;
|
||||
@ -309,6 +359,8 @@ class equal_to
|
||||
}
|
||||
return x1.tag_ != x2.tag_;
|
||||
}
|
||||
|
||||
friend less create_compare(equal_to x) { return less(x.tag_); }
|
||||
};
|
||||
|
||||
template <class T> class allocator
|
||||
@ -339,19 +391,11 @@ template <class T> class allocator
|
||||
|
||||
template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator::allocator())
|
||||
{
|
||||
UNORDERED_EPOINT("Mock allocator template copy constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
allocator(allocator const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator::allocator())
|
||||
{
|
||||
UNORDERED_EPOINT("Mock allocator copy constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
@ -359,11 +403,7 @@ template <class T> class allocator
|
||||
|
||||
allocator& operator=(allocator const& x)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator::allocator())
|
||||
{
|
||||
UNORDERED_EPOINT("Mock allocator assignment operator.");
|
||||
tag_ = x.tag_;
|
||||
}
|
||||
tag_ = x.tag_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -530,42 +570,22 @@ template <class T> class allocator2
|
||||
|
||||
allocator2(allocator<T> const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2())
|
||||
{
|
||||
UNORDERED_EPOINT("Mock allocator2 constructor from allocator.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2())
|
||||
{
|
||||
UNORDERED_EPOINT("Mock allocator2 template copy constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
allocator2(allocator2 const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2())
|
||||
{
|
||||
UNORDERED_EPOINT("Mock allocator2 copy constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
~allocator2() { test::detail::tracker.allocator_unref(); }
|
||||
|
||||
allocator2& operator=(allocator2 const& x)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2())
|
||||
{
|
||||
UNORDERED_EPOINT("Mock allocator2 assignment operator.");
|
||||
tag_ = x.tag_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
allocator2& operator=(allocator2 const&) { return *this; }
|
||||
|
||||
// If address throws, then it can't be used in erase or the
|
||||
// destructor, which is very limiting. I need to check up on
|
||||
@ -704,6 +724,14 @@ inline bool operator!=(allocator2<T> const& x, allocator2<T> const& y)
|
||||
}
|
||||
}
|
||||
|
||||
namespace test {
|
||||
template <typename X> struct equals_to_compare;
|
||||
template <> struct equals_to_compare<test::exception::equal_to>
|
||||
{
|
||||
typedef test::exception::less type;
|
||||
};
|
||||
}
|
||||
|
||||
// Workaround for ADL deficient compilers
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
namespace test {
|
||||
|
@ -391,21 +391,37 @@ template <class T> class allocator1
|
||||
::operator delete((void*)p);
|
||||
}
|
||||
|
||||
void construct(T* p, T const& t)
|
||||
#if BOOST_UNORDERED_CXX11_CONSTRUCTION
|
||||
template <typename U, typename... Args> void construct(U* p, Args&&... args)
|
||||
{
|
||||
// Don't count constructions here as it isn't always called.
|
||||
// detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
new (p) T(t);
|
||||
detail::tracker.track_construct((void*)p, sizeof(U), tag_);
|
||||
new (p) U(boost::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void destroy(T* p)
|
||||
template <typename U> void destroy(U* p)
|
||||
{
|
||||
// detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
|
||||
p->~T();
|
||||
detail::tracker.track_destroy((void*)p, sizeof(U), tag_);
|
||||
p->~U();
|
||||
|
||||
// Work around MSVC buggy unused parameter warning.
|
||||
ignore_variable(&p);
|
||||
}
|
||||
#else
|
||||
private:
|
||||
// I'm going to claim in the documentation that construct/destroy
|
||||
// is never used when C++11 support isn't available, so might as
|
||||
// well check that in the text.
|
||||
// TODO: Or maybe just disallow them for values?
|
||||
template <typename U> void construct(U* p);
|
||||
template <typename U, typename A0> void construct(U* p, A0 const&);
|
||||
template <typename U, typename A0, typename A1>
|
||||
void construct(U* p, A0 const&, A1 const&);
|
||||
template <typename U, typename A0, typename A1, typename A2>
|
||||
void construct(U* p, A0 const&, A1 const&, A2 const&);
|
||||
template <typename U> void destroy(U* p);
|
||||
|
||||
public:
|
||||
#endif
|
||||
|
||||
bool operator==(allocator1 const& x) const { return tag_ == x.tag_; }
|
||||
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/equivalent.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
#endif
|
||||
@ -32,7 +30,7 @@ template <class T> void assign_tests1(T*, test::random_generator generator)
|
||||
BOOST_DEDUCED_TYPENAME T::hasher hf;
|
||||
BOOST_DEDUCED_TYPENAME T::key_equal eq;
|
||||
|
||||
std::cerr << "assign_tests1.1\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -43,7 +41,7 @@ template <class T> void assign_tests1(T*, test::random_generator generator)
|
||||
BOOST_TEST(test::equivalent(x.key_eq(), eq));
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests1.2\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -79,7 +77,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
|
||||
|
||||
std::cerr << "assign_tests2.0 - empty container\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.0 - empty container\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -93,7 +91,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
test::check_container(x1, x2);
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.1\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -110,7 +108,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.1a\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1a\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -128,7 +126,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.2\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.2\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -150,7 +148,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.3\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.3\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -172,7 +170,7 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr << "assign_tests2.4\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.4\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -271,7 +269,7 @@ UNORDERED_TEST(
|
||||
|
||||
UNORDERED_AUTO_TEST(assign_default_initializer_list)
|
||||
{
|
||||
std::cerr << "Initializer List Tests\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
|
||||
std::initializer_list<std::pair<int const, int> > init;
|
||||
boost::unordered_map<int, int> x1;
|
||||
x1[25] = 3;
|
||||
@ -286,7 +284,7 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list)
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
UNORDERED_AUTO_TEST(assign_initializer_list)
|
||||
{
|
||||
std::cerr << "Initializer List Tests\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
|
||||
|
||||
boost::unordered_set<int> x;
|
||||
x.insert(10);
|
||||
|
@ -19,6 +19,21 @@ UNORDERED_AUTO_TEST(at_tests)
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
|
||||
|
||||
boost::unordered_map<std::string, int> x;
|
||||
boost::unordered_map<std::string, int> const& x_const(x);
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
|
||||
|
||||
try {
|
||||
x.at("one");
|
||||
BOOST_ERROR("Should have thrown.");
|
||||
} catch (std::out_of_range) {
|
||||
}
|
||||
|
||||
try {
|
||||
x_const.at("one");
|
||||
BOOST_ERROR("Should have thrown.");
|
||||
} catch (std::out_of_range) {
|
||||
}
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
|
||||
|
||||
@ -29,6 +44,8 @@ UNORDERED_AUTO_TEST(at_tests)
|
||||
|
||||
BOOST_TEST(x.at("one") == 1);
|
||||
BOOST_TEST(x.at("two") == 2);
|
||||
BOOST_TEST(x_const.at("one") == 1);
|
||||
BOOST_TEST(x_const.at("two") == 2);
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl;
|
||||
|
||||
@ -38,6 +55,12 @@ UNORDERED_AUTO_TEST(at_tests)
|
||||
} catch (std::out_of_range) {
|
||||
}
|
||||
|
||||
try {
|
||||
x_const.at("three");
|
||||
BOOST_ERROR("Should have thrown.");
|
||||
} catch (std::out_of_range) {
|
||||
}
|
||||
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,8 @@ template <class X> void tests(X*, test::random_generator generator)
|
||||
|
||||
BOOST_TEST(x.bucket_count() <= x.max_bucket_count());
|
||||
if (!(x.bucket_count() <= x.max_bucket_count())) {
|
||||
std::cerr << x.bucket_count() << "<=" << x.max_bucket_count() << "\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x.bucket_count()
|
||||
<< "<=" << x.max_bucket_count() << "\n";
|
||||
}
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "../helpers/postfix.hpp"
|
||||
// clang-format on
|
||||
|
||||
#include <iostream>
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/minimal.hpp"
|
||||
#include "./compile_tests.hpp"
|
||||
@ -46,7 +45,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
value_type;
|
||||
value_type value(x, x);
|
||||
|
||||
std::cout << "Test unordered_map.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
|
||||
|
||||
boost::unordered_map<int, int> int_map;
|
||||
|
||||
@ -64,7 +63,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
container_test(int_map2, std::pair<int const, int>(0, 0));
|
||||
container_test(map, value);
|
||||
|
||||
std::cout << "Test unordered_multimap.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
|
||||
|
||||
boost::unordered_multimap<int, int> int_multimap;
|
||||
|
||||
@ -139,7 +138,7 @@ UNORDERED_AUTO_TEST(test1)
|
||||
int value = 0;
|
||||
std::pair<int const, int> map_value(0, 0);
|
||||
|
||||
std::cout << "Test unordered_map.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
|
||||
|
||||
boost::unordered_map<int, int> map;
|
||||
|
||||
@ -157,7 +156,7 @@ UNORDERED_AUTO_TEST(test1)
|
||||
unordered_copyable_test(map2, value, map_value, hash, equal_to);
|
||||
unordered_map_functions(map2, value, value);
|
||||
|
||||
std::cout << "Test unordered_multimap.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
|
||||
|
||||
boost::unordered_multimap<int, int> multimap;
|
||||
|
||||
@ -188,7 +187,7 @@ UNORDERED_AUTO_TEST(test2)
|
||||
map_value_type;
|
||||
map_value_type map_value(assignable, assignable);
|
||||
|
||||
std::cout << "Test unordered_map.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
|
||||
|
||||
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
@ -212,7 +211,7 @@ UNORDERED_AUTO_TEST(test2)
|
||||
|
||||
unordered_map_functions(map2, assignable, default_assignable);
|
||||
|
||||
std::cout << "Test unordered_multimap.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
|
||||
|
||||
boost::unordered_multimap<test::minimal::assignable,
|
||||
test::minimal::assignable,
|
||||
@ -227,4 +226,36 @@ UNORDERED_AUTO_TEST(test2)
|
||||
unordered_map_member_test(multimap, map_value);
|
||||
}
|
||||
|
||||
// Test for ambiguity when using key convertible from iterator
|
||||
// See LWG2059
|
||||
|
||||
struct lwg2059_key
|
||||
{
|
||||
int value;
|
||||
|
||||
template <typename T> lwg2059_key(T v) : value(v) {}
|
||||
};
|
||||
|
||||
std::size_t hash_value(lwg2059_key x)
|
||||
{
|
||||
return static_cast<std::size_t>(x.value);
|
||||
}
|
||||
|
||||
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
|
||||
|
||||
UNORDERED_AUTO_TEST(lwg2059)
|
||||
{
|
||||
{
|
||||
boost::unordered_map<lwg2059_key, int> x;
|
||||
x.emplace(lwg2059_key(10), 5);
|
||||
x.erase(x.begin());
|
||||
}
|
||||
|
||||
{
|
||||
boost::unordered_multimap<lwg2059_key, int> x;
|
||||
x.emplace(lwg2059_key(10), 5);
|
||||
x.erase(x.begin());
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "../helpers/postfix.hpp"
|
||||
// clang-format on
|
||||
|
||||
#include <iostream>
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../objects/minimal.hpp"
|
||||
#include "./compile_tests.hpp"
|
||||
@ -42,7 +41,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
|
||||
test::minimal::assignable assignable(x);
|
||||
|
||||
std::cout << "Test unordered_set.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<int> int_set;
|
||||
|
||||
@ -60,7 +59,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
container_test(int_set2, 0);
|
||||
container_test(set, assignable);
|
||||
|
||||
std::cout << "Test unordered_multiset.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<int> int_multiset;
|
||||
|
||||
@ -128,7 +127,7 @@ UNORDERED_AUTO_TEST(test1)
|
||||
std::equal_to<int> equal_to;
|
||||
int value = 0;
|
||||
|
||||
std::cout << "Test unordered_set." << std::endl;
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set." << std::endl;
|
||||
|
||||
boost::unordered_set<int> set;
|
||||
|
||||
@ -144,7 +143,7 @@ UNORDERED_AUTO_TEST(test1)
|
||||
unordered_set_test(set2, value);
|
||||
unordered_copyable_test(set2, value, value, hash, equal_to);
|
||||
|
||||
std::cout << "Test unordered_multiset." << std::endl;
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset." << std::endl;
|
||||
|
||||
boost::unordered_multiset<int> multiset;
|
||||
|
||||
@ -170,7 +169,7 @@ UNORDERED_AUTO_TEST(test2)
|
||||
test::minimal::hash<test::minimal::assignable> hash(x);
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
|
||||
|
||||
std::cout << "Test unordered_set.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
@ -183,7 +182,7 @@ UNORDERED_AUTO_TEST(test2)
|
||||
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
|
||||
unordered_set_member_test(set, assignable);
|
||||
|
||||
std::cout << "Test unordered_multiset.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
@ -205,7 +204,7 @@ UNORDERED_AUTO_TEST(movable1_tests)
|
||||
test::minimal::hash<test::minimal::movable1> hash(x);
|
||||
test::minimal::equal_to<test::minimal::movable1> equal_to(x);
|
||||
|
||||
std::cout << "Test unordered_set.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<test::minimal::movable1,
|
||||
test::minimal::hash<test::minimal::movable1>,
|
||||
@ -217,7 +216,7 @@ UNORDERED_AUTO_TEST(movable1_tests)
|
||||
unordered_set_test(set, movable1);
|
||||
unordered_movable_test(set, movable1, movable1, hash, equal_to);
|
||||
|
||||
std::cout << "Test unordered_multiset.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<test::minimal::movable1,
|
||||
test::minimal::hash<test::minimal::movable1>,
|
||||
@ -238,7 +237,7 @@ UNORDERED_AUTO_TEST(movable2_tests)
|
||||
test::minimal::hash<test::minimal::movable2> hash(x);
|
||||
test::minimal::equal_to<test::minimal::movable2> equal_to(x);
|
||||
|
||||
std::cout << "Test unordered_set.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<test::minimal::movable2,
|
||||
test::minimal::hash<test::minimal::movable2>,
|
||||
@ -250,7 +249,7 @@ UNORDERED_AUTO_TEST(movable2_tests)
|
||||
unordered_set_test(set, movable2);
|
||||
unordered_movable_test(set, movable2, movable2, hash, equal_to);
|
||||
|
||||
std::cout << "Test unordered_multiset.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<test::minimal::movable2,
|
||||
test::minimal::hash<test::minimal::movable2>,
|
||||
@ -271,7 +270,7 @@ UNORDERED_AUTO_TEST(destructible_tests)
|
||||
test::minimal::hash<test::minimal::destructible> hash(x);
|
||||
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
|
||||
|
||||
std::cout << "Test unordered_set.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
|
||||
|
||||
boost::unordered_set<test::minimal::destructible,
|
||||
test::minimal::hash<test::minimal::destructible>,
|
||||
@ -280,7 +279,7 @@ UNORDERED_AUTO_TEST(destructible_tests)
|
||||
|
||||
unordered_destructible_test(set);
|
||||
|
||||
std::cout << "Test unordered_multiset.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
|
||||
|
||||
boost::unordered_multiset<test::minimal::destructible,
|
||||
test::minimal::hash<test::minimal::destructible>,
|
||||
@ -290,4 +289,36 @@ UNORDERED_AUTO_TEST(destructible_tests)
|
||||
unordered_destructible_test(multiset);
|
||||
}
|
||||
|
||||
// Test for ambiguity when using key convertible from iterator
|
||||
// See LWG2059
|
||||
|
||||
struct lwg2059_key
|
||||
{
|
||||
int value;
|
||||
|
||||
template <typename T> lwg2059_key(T v) : value(v) {}
|
||||
};
|
||||
|
||||
std::size_t hash_value(lwg2059_key x)
|
||||
{
|
||||
return static_cast<std::size_t>(x.value);
|
||||
}
|
||||
|
||||
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
|
||||
|
||||
UNORDERED_AUTO_TEST(lwg2059)
|
||||
{
|
||||
{
|
||||
boost::unordered_set<lwg2059_key> x;
|
||||
x.emplace(lwg2059_key(10));
|
||||
x.erase(x.begin());
|
||||
}
|
||||
|
||||
{
|
||||
boost::unordered_multiset<lwg2059_key> x;
|
||||
x.emplace(lwg2059_key(10));
|
||||
x.erase(x.begin());
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -19,7 +19,9 @@
|
||||
#include "../helpers/check_return_type.hpp"
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/predef.h>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/cv_traits.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
@ -30,6 +32,23 @@ template <class T> void sink(T const&) {}
|
||||
template <class T> T rvalue(T const& v) { return v; }
|
||||
template <class T> T rvalue_default() { return T(); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
template <class T> T implicit_construct() { return {}; }
|
||||
#else
|
||||
template <class T> int implicit_construct()
|
||||
{
|
||||
T x;
|
||||
sink(x);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
|
||||
#define TEST_NOEXCEPT_EXPR(x) BOOST_STATIC_ASSERT((BOOST_NOEXCEPT_EXPR(x)));
|
||||
#else
|
||||
#define TEST_NOEXCEPT_EXPR(x)
|
||||
#endif
|
||||
|
||||
template <class X, class T> void container_test(X& r, T const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
@ -52,6 +71,8 @@ template <class X, class T> void container_test(X& r, T const&)
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
|
||||
// value_type
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
|
||||
@ -75,7 +96,9 @@ template <class X, class T> void container_test(X& r, T const&)
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
|
||||
|
||||
// node_type
|
||||
// TODO?
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<allocator_type,
|
||||
BOOST_DEDUCED_TYPENAME node_type::allocator_type>::value));
|
||||
|
||||
// difference_type
|
||||
|
||||
@ -134,7 +157,6 @@ template <class X, class T> void container_test(X& r, T const&)
|
||||
|
||||
// Allocator
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
|
||||
|
||||
allocator_type m = a.get_allocator();
|
||||
@ -147,21 +169,30 @@ template <class X, class T> void container_test(X& r, T const&)
|
||||
|
||||
// node_type
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<allocator_type,
|
||||
BOOST_DEDUCED_TYPENAME node_type::allocator_type>::value));
|
||||
implicit_construct<node_type const>();
|
||||
#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
|
||||
TEST_NOEXCEPT_EXPR(node_type());
|
||||
#endif
|
||||
|
||||
node_type n1;
|
||||
node_type n2(rvalue_default<node_type>());
|
||||
#if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0)
|
||||
TEST_NOEXCEPT_EXPR(node_type(boost::move(n1)));
|
||||
#endif
|
||||
node_type n3;
|
||||
n3 = boost::move(n2);
|
||||
n1.swap(n3);
|
||||
swap(n1, n3);
|
||||
// TODO: noexcept for swap?
|
||||
// value, key, mapped tests in map and set specific testing.
|
||||
|
||||
node_type const n_const;
|
||||
BOOST_TEST(n_const ? 0 : 1);
|
||||
TEST_NOEXCEPT_EXPR(n_const ? 0 : 1);
|
||||
test::check_return_type<bool>::equals(!n_const);
|
||||
test::check_return_type<bool>::equals(n_const.empty());
|
||||
TEST_NOEXCEPT_EXPR(!n_const);
|
||||
TEST_NOEXCEPT_EXPR(n_const.empty());
|
||||
|
||||
// Avoid unused variable warnings:
|
||||
|
||||
@ -302,14 +333,22 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Key, node_key_type>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T, node_mapped_type>::value));
|
||||
// Superfluous,but just to make sure.
|
||||
BOOST_STATIC_ASSERT((!boost::is_const<node_key_type>::value));
|
||||
|
||||
// Calling functions
|
||||
|
||||
r.insert(std::pair<Key const, T>(k, v));
|
||||
r.insert(r.begin(), std::pair<Key const, T>(k, v));
|
||||
std::pair<Key const, T> const value(k, v);
|
||||
r.insert(value);
|
||||
r.insert(r.end(), value);
|
||||
|
||||
Key k_lvalue(k);
|
||||
T v_lvalue(v);
|
||||
|
||||
// Emplace
|
||||
|
||||
r.emplace(k, v);
|
||||
r.emplace(k_lvalue, v_lvalue);
|
||||
r.emplace(rvalue(k), rvalue(v));
|
||||
@ -317,6 +356,17 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
r.emplace(boost::unordered::piecewise_construct, boost::make_tuple(k),
|
||||
boost::make_tuple(v));
|
||||
|
||||
// Emplace with hint
|
||||
|
||||
r.emplace_hint(r.begin(), k, v);
|
||||
r.emplace_hint(r.begin(), k_lvalue, v_lvalue);
|
||||
r.emplace_hint(r.begin(), rvalue(k), rvalue(v));
|
||||
|
||||
r.emplace_hint(r.begin(), boost::unordered::piecewise_construct,
|
||||
boost::make_tuple(k), boost::make_tuple(v));
|
||||
|
||||
// Extract
|
||||
|
||||
test::check_return_type<node_type>::equals(r.extract(r.begin()));
|
||||
|
||||
r.emplace(k, v);
|
||||
@ -327,8 +377,16 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
test::check_return_type<key_type>::equals_ref(n1.key());
|
||||
test::check_return_type<T>::equals_ref(n1.mapped());
|
||||
|
||||
r.insert(boost::move(n1));
|
||||
node_type n2 = boost::move(n1);
|
||||
r.insert(boost::move(n2));
|
||||
r.insert(r.extract(r.begin()));
|
||||
n2 = r.extract(r.begin());
|
||||
r.insert(r.begin(), boost::move(n2));
|
||||
r.insert(r.end(), r.extract(r.begin()));
|
||||
|
||||
node_type n = r.extract(r.begin());
|
||||
test::check_return_type<node_key_type>::equals_ref(n.key());
|
||||
test::check_return_type<node_mapped_type>::equals_ref(n.mapped());
|
||||
}
|
||||
|
||||
template <class X> void equality_test(X& r)
|
||||
@ -385,6 +443,7 @@ void unordered_map_functions(X&, Key const& k, T const& v)
|
||||
|
||||
X a;
|
||||
test::check_return_type<mapped_type>::equals_ref(a[k]);
|
||||
test::check_return_type<mapped_type>::equals_ref(a[rvalue(k)]);
|
||||
test::check_return_type<mapped_type>::equals_ref(a.at(k));
|
||||
test::check_return_type<std::pair<iterator, bool> >::equals(
|
||||
a.try_emplace(k, v));
|
||||
@ -517,6 +576,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
|
||||
const_iterator q1 = a.cbegin(), q2 = a.cend();
|
||||
test::check_return_type<iterator>::equals(a.erase(q1, q2));
|
||||
|
||||
TEST_NOEXCEPT_EXPR(a.clear());
|
||||
a.clear();
|
||||
|
||||
X const b;
|
||||
@ -627,6 +687,13 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
sink(X(b, m));
|
||||
X a9a(b, m);
|
||||
|
||||
X b1;
|
||||
b1.insert(t);
|
||||
X a9b(b1);
|
||||
sink(a9b);
|
||||
X a9c(b1, m);
|
||||
sink(a9c);
|
||||
|
||||
const_iterator q = a.cbegin();
|
||||
|
||||
test::check_return_type<iterator>::equals(a.insert(q, t));
|
||||
@ -638,7 +705,9 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
a.insert(list);
|
||||
a.insert({t, t, t});
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) && \
|
||||
(!defined(__clang__) || __clang_major__ >= 4 || \
|
||||
(__clang_major__ == 3 && __clang_minor__ >= 4))
|
||||
a.insert({});
|
||||
a.insert({t});
|
||||
a.insert({t, t});
|
||||
|
@ -28,7 +28,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
BOOST_DEDUCED_TYPENAME T::key_equal eq;
|
||||
BOOST_DEDUCED_TYPENAME T::allocator_type al;
|
||||
|
||||
std::cerr << "Construct 1\n";
|
||||
UNORDERED_SUB_TEST("Construct 1")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -40,7 +40,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 2\n";
|
||||
UNORDERED_SUB_TEST("Construct 2")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -53,7 +53,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 3\n";
|
||||
UNORDERED_SUB_TEST("Construct 3")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -66,7 +66,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 4\n";
|
||||
UNORDERED_SUB_TEST("Construct 4")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -78,7 +78,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 5\n";
|
||||
UNORDERED_SUB_TEST("Construct 5")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -92,7 +92,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 6\n";
|
||||
UNORDERED_SUB_TEST("Construct 6")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -106,7 +106,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 7\n";
|
||||
UNORDERED_SUB_TEST("Construct 7")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -120,7 +120,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 8\n";
|
||||
UNORDERED_SUB_TEST("Construct 8")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -133,7 +133,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 9\n";
|
||||
UNORDERED_SUB_TEST("Construct 9")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -145,7 +145,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 10\n";
|
||||
UNORDERED_SUB_TEST("Construct 10")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -159,7 +159,7 @@ template <class T> void constructor_tests1(T*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 11\n";
|
||||
UNORDERED_SUB_TEST("Construct 11")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -185,7 +185,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
|
||||
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
|
||||
|
||||
std::cerr << "Construct 1\n";
|
||||
UNORDERED_SUB_TEST("Construct 1")
|
||||
{
|
||||
test::check_instances check_;
|
||||
T x(10000, hf1, eq1);
|
||||
@ -196,7 +196,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 2\n";
|
||||
UNORDERED_SUB_TEST("Construct 2")
|
||||
{
|
||||
test::check_instances check_;
|
||||
T x(100, hf1);
|
||||
@ -208,7 +208,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 3\n";
|
||||
UNORDERED_SUB_TEST("Construct 3")
|
||||
{
|
||||
test::check_instances check_;
|
||||
test::random_values<T> v(100, generator);
|
||||
@ -220,7 +220,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 4\n";
|
||||
UNORDERED_SUB_TEST("Construct 4")
|
||||
{
|
||||
test::check_instances check_;
|
||||
test::random_values<T> v(5, generator);
|
||||
@ -233,7 +233,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 5\n";
|
||||
UNORDERED_SUB_TEST("Construct 5")
|
||||
{
|
||||
test::check_instances check_;
|
||||
test::random_values<T> v(100, generator);
|
||||
@ -245,7 +245,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 6\n";
|
||||
UNORDERED_SUB_TEST("Construct 6")
|
||||
{
|
||||
test::check_instances check_;
|
||||
test::random_values<T> v(100, generator);
|
||||
@ -257,7 +257,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 7\n";
|
||||
UNORDERED_SUB_TEST("Construct 7")
|
||||
{
|
||||
test::check_instances check_;
|
||||
test::random_values<T> v(100, generator);
|
||||
@ -269,7 +269,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 8 - from input iterator\n";
|
||||
UNORDERED_SUB_TEST("Construct 8 - from input iterator")
|
||||
{
|
||||
test::check_instances check_;
|
||||
test::random_values<T> v(100, generator);
|
||||
@ -288,7 +288,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 8.5 - from copy iterator\n";
|
||||
UNORDERED_SUB_TEST("Construct 8.5 - from copy iterator")
|
||||
{
|
||||
test::check_instances check_;
|
||||
test::random_values<T> v(100, generator);
|
||||
@ -302,7 +302,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
std::cerr << "Construct 9\n";
|
||||
UNORDERED_SUB_TEST("Construct 9")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -320,7 +320,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
|
||||
|
||||
std::cerr << "Initializer list construct 1\n";
|
||||
UNORDERED_SUB_TEST("Initializer list construct 1")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -331,7 +331,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
std::cerr << "Initializer list construct 2\n";
|
||||
UNORDERED_SUB_TEST("Initializer list construct 2")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -343,7 +343,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
std::cerr << "Initializer list construct 3\n";
|
||||
UNORDERED_SUB_TEST("Initializer list construct 3")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -355,7 +355,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
std::cerr << "Initializer list construct 4\n";
|
||||
UNORDERED_SUB_TEST("Initializer list construct 4")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -367,7 +367,7 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
BOOST_TEST(test::equivalent(x.get_allocator(), al));
|
||||
}
|
||||
|
||||
std::cerr << "Initializer list construct 5\n";
|
||||
UNORDERED_SUB_TEST("Initializer list construct 5")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -384,8 +384,6 @@ void constructor_tests2(T*, test::random_generator const& generator)
|
||||
template <class T>
|
||||
void map_constructor_test(T*, test::random_generator const& generator)
|
||||
{
|
||||
std::cerr << "map_constructor_test\n";
|
||||
|
||||
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME T::key_type,
|
||||
BOOST_DEDUCED_TYPENAME T::mapped_type> >
|
||||
list;
|
||||
@ -429,7 +427,6 @@ UNORDERED_TEST(map_constructor_test,
|
||||
|
||||
UNORDERED_AUTO_TEST(test_default_initializer_list)
|
||||
{
|
||||
std::cerr << "Initializer List Tests\n";
|
||||
std::initializer_list<int> init;
|
||||
boost::unordered_set<int> x1 = init;
|
||||
BOOST_TEST(x1.empty());
|
||||
@ -441,7 +438,6 @@ UNORDERED_AUTO_TEST(test_default_initializer_list)
|
||||
|
||||
UNORDERED_AUTO_TEST(test_initializer_list)
|
||||
{
|
||||
std::cerr << "Initializer List Tests\n";
|
||||
boost::unordered_set<int> x1 = {2, 10, 45, -5};
|
||||
BOOST_TEST(x1.find(10) != x1.end());
|
||||
BOOST_TEST(x1.find(46) == x1.end());
|
||||
@ -450,4 +446,4 @@ UNORDERED_AUTO_TEST(test_initializer_list)
|
||||
#endif
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
RUN_TESTS_QUIET()
|
||||
|
102
test/unordered/detail_tests.cpp
Normal file
102
test/unordered/detail_tests.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
|
||||
// Copyright 2017 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// clang-format off
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
// clang-format on
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
#include <map>
|
||||
|
||||
// Pretty inefficient, but the test is fast enough.
|
||||
// Might be too slow if we had larger primes?
|
||||
bool is_prime(std::size_t x)
|
||||
{
|
||||
if (x == 2) {
|
||||
return true;
|
||||
} else if (x == 1 || x % 2 == 0) {
|
||||
return false;
|
||||
} else {
|
||||
// y*y <= x had rounding errors, so instead use y <= (x/y).
|
||||
for (std::size_t y = 3; y <= (x / y); y += 2) {
|
||||
if (x % y == 0) {
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void test_next_prime(std::size_t value)
|
||||
{
|
||||
std::size_t x = boost::unordered::detail::next_prime(value);
|
||||
BOOST_TEST(is_prime(x));
|
||||
BOOST_TEST(x >= value);
|
||||
}
|
||||
|
||||
void test_prev_prime(std::size_t value)
|
||||
{
|
||||
std::size_t x = boost::unordered::detail::prev_prime(value);
|
||||
BOOST_TEST(is_prime(x));
|
||||
BOOST_TEST(x <= value);
|
||||
if (x > value) {
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x << "," << value << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(next_prime_test)
|
||||
{
|
||||
BOOST_TEST(!is_prime(0));
|
||||
BOOST_TEST(!is_prime(1));
|
||||
BOOST_TEST(is_prime(2));
|
||||
BOOST_TEST(is_prime(3));
|
||||
BOOST_TEST(is_prime(13));
|
||||
BOOST_TEST(!is_prime(4));
|
||||
BOOST_TEST(!is_prime(100));
|
||||
|
||||
BOOST_TEST(boost::unordered::detail::next_prime(0) > 0);
|
||||
|
||||
// test_prev_prime doesn't work for values less than 17.
|
||||
// Which should be okay, unless an allocator has a really tiny
|
||||
// max_size?
|
||||
const std::size_t min_prime = 17;
|
||||
|
||||
// test_next_prime doesn't work for values greater than this,
|
||||
// which might be a problem if you've got terrabytes of memory?
|
||||
// I seriously doubt the container would work well at such sizes
|
||||
// regardless.
|
||||
const std::size_t max_prime = 4294967291ul;
|
||||
|
||||
std::size_t i;
|
||||
|
||||
BOOST_TEST(is_prime(min_prime));
|
||||
BOOST_TEST(is_prime(max_prime));
|
||||
|
||||
for (i = 0; i < 10000; ++i) {
|
||||
if (i < min_prime) {
|
||||
BOOST_TEST(boost::unordered::detail::prev_prime(i) == min_prime);
|
||||
} else {
|
||||
test_prev_prime(i);
|
||||
}
|
||||
test_next_prime(i);
|
||||
}
|
||||
|
||||
std::size_t last = i - 1;
|
||||
for (; i > last; last = i, i += i / 5) {
|
||||
if (i > max_prime) {
|
||||
BOOST_TEST(boost::unordered::detail::next_prime(i) == max_prime);
|
||||
} else {
|
||||
test_next_prime(i);
|
||||
}
|
||||
test_prev_prime(i);
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
@ -17,8 +17,6 @@
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class Container, class Iterator>
|
||||
void test_equal_insertion(Iterator begin, Iterator end)
|
||||
{
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include "../objects/test.hpp"
|
||||
|
||||
@ -31,14 +30,15 @@ struct write_pair_type
|
||||
template <class X1, class X2>
|
||||
void operator()(std::pair<X1, X2> const& x) const
|
||||
{
|
||||
std::cout << "(" << x.first << "," << x.second << ")";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "(" << x.first << "," << x.second
|
||||
<< ")";
|
||||
}
|
||||
} write_pair;
|
||||
|
||||
template <class Container> void write_container(Container const& x)
|
||||
{
|
||||
std::for_each(x.begin(), x.end(), write_pair);
|
||||
std::cout << "\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
|
||||
}
|
||||
|
||||
// Make everything collide - for testing erase in a single bucket.
|
||||
@ -165,8 +165,8 @@ template <class Container> void erase_subrange_tests(Container const& x)
|
||||
collide_list init(y.begin(), y.end());
|
||||
if (!general_erase_range_test(y, position, position + length)) {
|
||||
BOOST_ERROR("general_erase_range_test failed.");
|
||||
std::cout << "Erase: [" << position << "," << position + length
|
||||
<< ")\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase: [" << position << ","
|
||||
<< position + length << ")\n";
|
||||
write_container(init);
|
||||
write_container(y);
|
||||
}
|
||||
@ -185,7 +185,8 @@ void x_by_y_erase_range_tests(Container*, int values, int duplicates)
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Values: " << values << ", Duplicates: " << duplicates << "\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Values: " << values
|
||||
<< ", Duplicates: " << duplicates << "\n";
|
||||
erase_subrange_tests(y);
|
||||
}
|
||||
|
||||
@ -201,24 +202,24 @@ void exhaustive_erase_tests(Container* x, int num_values, int num_duplicated)
|
||||
|
||||
UNORDERED_AUTO_TEST(exhaustive_collide_tests)
|
||||
{
|
||||
std::cout << "exhaustive_collide_tests:\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide_tests:\n";
|
||||
collide_map m;
|
||||
exhaustive_erase_tests((collide_map*)0, 4, 4);
|
||||
std::cout << "\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
|
||||
{
|
||||
std::cout << "exhaustive_collide2_tests:\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide2_tests:\n";
|
||||
exhaustive_erase_tests((collide_map2*)0, 8, 4);
|
||||
std::cout << "\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(exhaustive_collide3_tests)
|
||||
{
|
||||
std::cout << "exhaustive_collide3_tests:\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide3_tests:\n";
|
||||
exhaustive_erase_tests((collide_map3*)0, 8, 4);
|
||||
std::cout << "\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "../helpers/helpers.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace erase_tests {
|
||||
@ -31,7 +30,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME Container::const_iterator c_iterator;
|
||||
|
||||
std::cerr << "Erase by key.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -52,7 +51,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "erase(begin()).\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(begin()).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -75,7 +74,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "erase(random position).\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random position).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -104,7 +103,8 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
index == 0 ? next == x.begin() : next == test::next(prev));
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
if (x.count(key) != count - 1) {
|
||||
std::cerr << count << " => " << x.count(key) << std::endl;
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => "
|
||||
<< x.count(key) << std::endl;
|
||||
}
|
||||
BOOST_TEST(x.size() == size);
|
||||
if (++iterations % 20 == 0)
|
||||
@ -113,7 +113,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "erase(ranges).\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(ranges).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -140,7 +140,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "erase(random ranges).\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random ranges).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
Container x;
|
||||
@ -179,7 +179,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "quick_erase(begin()).\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(begin()).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -201,7 +201,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "quick_erase(random position).\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(random position).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -230,7 +230,8 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
index == 0 ? next == x.begin() : next == test::next(prev));
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
if (x.count(key) != count - 1) {
|
||||
std::cerr << count << " => " << x.count(key) << std::endl;
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => "
|
||||
<< x.count(key) << std::endl;
|
||||
}
|
||||
BOOST_TEST(x.size() == size);
|
||||
if (++iterations % 20 == 0)
|
||||
@ -239,7 +240,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "clear().\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "clear().\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -250,7 +251,7 @@ void erase_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.begin() == x.end());
|
||||
}
|
||||
|
||||
std::cerr << "\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
|
||||
}
|
||||
|
||||
boost::unordered_set<test::object, test::hash, test::equal_to,
|
||||
|
@ -19,8 +19,6 @@
|
||||
#include "../objects/test.hpp"
|
||||
#include <boost/next_prior.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace extract_tests {
|
||||
|
||||
test::seed_t initialize_seed(85638);
|
||||
@ -28,7 +26,7 @@ test::seed_t initialize_seed(85638);
|
||||
template <class Container>
|
||||
void extract_tests1(Container*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "Extract by key.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Extract by key.\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -58,7 +56,7 @@ void extract_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "extract(begin()).\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(begin()).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -81,7 +79,7 @@ void extract_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "extract(random position).\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(random position).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -117,7 +115,7 @@ void extract_tests1(Container*, test::random_generator generator)
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
|
||||
}
|
||||
|
||||
boost::unordered_set<test::object, test::hash, test::equal_to,
|
||||
|
@ -65,6 +65,11 @@ template <typename T> struct allocator : std::allocator<T>
|
||||
allocator(const allocator<T2>& other) : std::allocator<T>(other)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
allocator(const std::allocator<T2>& other) : std::allocator<T>(other)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Declare some members of a structs.
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
namespace insert_hint {
|
||||
UNORDERED_AUTO_TEST(insert_hint_empty)
|
||||
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace insert_stable {
|
||||
struct member
|
||||
{
|
||||
@ -47,9 +45,9 @@ std::size_t hash_value(insert_stable::member const& x)
|
||||
}
|
||||
}
|
||||
|
||||
// This is now only supported when using grouped nodes. I can't see any
|
||||
// efficient way to do it otherwise.
|
||||
#if !BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
// This is no longer supported, as there's no longer an efficient way to get to
|
||||
// the end of a group of equivalent nodes.
|
||||
#if 0
|
||||
|
||||
UNORDERED_AUTO_TEST(stable_insert_test1)
|
||||
{
|
||||
|
@ -3,6 +3,8 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(PIECEWISE_TEST_NAME)
|
||||
|
||||
// clang-format off
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_set.hpp>
|
||||
@ -19,8 +21,6 @@
|
||||
#include "../helpers/input_iterator.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace insert_tests {
|
||||
|
||||
test::seed_t initialize_seed(243432);
|
||||
@ -33,66 +33,138 @@ void unique_insert_tests1(X*, test::random_generator generator)
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef test::ordered<X> ordered;
|
||||
|
||||
std::cerr << "insert(value) tests for containers with unique keys.\n";
|
||||
UNORDERED_SUB_TEST("insert(value) tests for containers with unique keys")
|
||||
{
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
test::random_values<X> v(1000, generator);
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
|
||||
v.begin();
|
||||
it != v.end(); ++it) {
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
|
||||
it != v.end(); ++it) {
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
|
||||
x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
std::pair<iterator, bool> r1 = x.insert(*it);
|
||||
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 =
|
||||
tracker.insert(*it);
|
||||
|
||||
std::pair<iterator, bool> r1 = x.insert(*it);
|
||||
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 =
|
||||
tracker.insert(*it);
|
||||
BOOST_TEST(r1.second == r2.second);
|
||||
BOOST_TEST(*r1.first == *r2.first);
|
||||
|
||||
BOOST_TEST(r1.second == r2.second);
|
||||
BOOST_TEST(*r1.first == *r2.first);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
if (static_cast<double>(x.size()) <=
|
||||
b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
if (static_cast<double>(x.size()) <=
|
||||
b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
UNORDERED_SUB_TEST("insert(rvalue) tests for containers with unique keys")
|
||||
{
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
|
||||
v.begin();
|
||||
it != v.end(); ++it) {
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
|
||||
x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
|
||||
typename X::value_type value = *it;
|
||||
std::pair<iterator, bool> r1 = x.insert(boost::move(value));
|
||||
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 =
|
||||
tracker.insert(*it);
|
||||
|
||||
BOOST_TEST(r1.second == r2.second);
|
||||
BOOST_TEST(*r1.first == *r2.first);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if (static_cast<double>(x.size()) <=
|
||||
b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
|
||||
template <class X>
|
||||
void equivalent_insert_tests1(X*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "insert(value) tests for containers with equivalent keys.\n";
|
||||
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
UNORDERED_SUB_TEST(
|
||||
"insert(value) tests for containers with equivalent keys")
|
||||
{
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
|
||||
it != v.end(); ++it) {
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
test::random_values<X> v(1000, generator);
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
|
||||
v.begin();
|
||||
it != v.end(); ++it) {
|
||||
BOOST_DEDUCED_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<X>::iterator r2 =
|
||||
tracker.insert(*it);
|
||||
BOOST_DEDUCED_TYPENAME X::iterator r1 = x.insert(*it);
|
||||
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2 =
|
||||
tracker.insert(*it);
|
||||
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if (static_cast<double>(x.size()) <=
|
||||
b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
if (static_cast<double>(x.size()) <=
|
||||
b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
UNORDERED_SUB_TEST(
|
||||
"insert(rvalue) tests for containers with equivalent keys")
|
||||
{
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
|
||||
v.begin();
|
||||
it != v.end(); ++it) {
|
||||
BOOST_DEDUCED_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<X>::iterator r2 =
|
||||
tracker.insert(*it);
|
||||
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if (static_cast<double>(x.size()) <=
|
||||
b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
}
|
||||
|
||||
template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
@ -102,8 +174,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
|
||||
typedef BOOST_DEDUCED_TYPENAME tracker_type::iterator tracker_iterator;
|
||||
|
||||
std::cerr << "insert(begin(), value) tests.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert(begin(), value) tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -132,8 +203,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert(end(), value) tests.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert(end(), value) tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -163,8 +233,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert(pos, value) tests.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert(pos, value) tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -194,8 +263,38 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert single item range tests.\n";
|
||||
UNORDERED_SUB_TEST("insert(pos, rvalue) tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
X x;
|
||||
const_iterator pos = x.begin();
|
||||
tracker_type tracker = test::create_ordered(x);
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
|
||||
v.begin();
|
||||
it != v.end(); ++it) {
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
|
||||
x.bucket_count();
|
||||
float b = x.max_load_factor();
|
||||
|
||||
typename X::value_type value = *it;
|
||||
pos = x.insert(pos, boost::move(value));
|
||||
tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
|
||||
BOOST_TEST(*pos == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if (static_cast<double>(x.size()) <=
|
||||
b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
tracker.compare(x);
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
UNORDERED_SUB_TEST("insert single item range tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -223,8 +322,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert range tests.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert range tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -237,8 +335,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert range with rehash tests.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert range with rehash tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -255,8 +352,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert input iterator range tests.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert input iterator range tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -272,8 +368,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert copy iterator range tests.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert copy iterator range tests")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -286,8 +381,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert copy iterator range test 2.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert copy iterator range test 2")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -303,8 +397,7 @@ template <class X> void insert_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert various ranges.\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert various ranges")
|
||||
{
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
X x;
|
||||
@ -350,8 +443,6 @@ void unique_emplace_tests1(X*, test::random_generator generator)
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
typedef test::ordered<X> ordered;
|
||||
|
||||
std::cerr << "emplace(value) tests for containers with unique keys.\n";
|
||||
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
@ -384,8 +475,6 @@ void unique_emplace_tests1(X*, test::random_generator generator)
|
||||
template <class X>
|
||||
void equivalent_emplace_tests1(X*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "emplace(value) tests for containers with equivalent keys.\n";
|
||||
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
@ -414,9 +503,6 @@ void equivalent_emplace_tests1(X*, test::random_generator generator)
|
||||
|
||||
template <class X> void move_emplace_tests(X*, test::random_generator generator)
|
||||
{
|
||||
std::cerr
|
||||
<< "emplace(move(value)) tests for containers with unique keys.\n";
|
||||
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
@ -444,8 +530,7 @@ template <class X> void move_emplace_tests(X*, test::random_generator generator)
|
||||
|
||||
template <class X> void default_emplace_tests(X*, test::random_generator)
|
||||
{
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
std::cerr << "emplace() tests.\n";
|
||||
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
|
||||
bool is_unique = test::has_unique_keys<X>::value;
|
||||
|
||||
X x;
|
||||
@ -480,8 +565,6 @@ template <class X> void default_emplace_tests(X*, test::random_generator)
|
||||
|
||||
template <class X> void map_tests(X*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "map tests.\n";
|
||||
|
||||
X x;
|
||||
test::ordered<X> tracker = test::create_ordered(x);
|
||||
|
||||
@ -508,8 +591,8 @@ template <class X> void map_tests(X*, test::random_generator generator)
|
||||
template <class X> void map_tests2(X*, test::random_generator generator)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
std::cerr << "insert_or_assign\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert_or_assign")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -540,8 +623,7 @@ template <class X> void map_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert_or_assign(begin)\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert_or_assign(begin)")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -571,8 +653,7 @@ template <class X> void map_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert_or_assign(end)\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert_or_assign(end)")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -602,8 +683,7 @@ template <class X> void map_tests2(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "insert_or_assign(last)\n";
|
||||
|
||||
UNORDERED_SUB_TEST("insert_or_assign(last)")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -639,10 +719,9 @@ template <class X> void map_tests2(X*, test::random_generator generator)
|
||||
|
||||
template <class X> void try_emplace_tests(X*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "try_emplace(key, value)\n";
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
|
||||
UNORDERED_SUB_TEST("try_emplace(key, value)")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -682,10 +761,9 @@ template <class X> void try_emplace_tests(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "try_emplace(begin(), key, value)\n";
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
|
||||
UNORDERED_SUB_TEST("try_emplace(begin(), key, value)")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -722,10 +800,9 @@ template <class X> void try_emplace_tests(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "try_emplace(end(), key, value)\n";
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
|
||||
UNORDERED_SUB_TEST("try_emplace(end(), key, value)")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -762,10 +839,9 @@ template <class X> void try_emplace_tests(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
|
||||
std::cerr << "try_emplace(pos, key, value)\n";
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
|
||||
UNORDERED_SUB_TEST("try_emplace(pos, key, value)")
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
@ -808,8 +884,6 @@ template <class X> void try_emplace_tests(X*, test::random_generator generator)
|
||||
template <class X>
|
||||
void map_insert_range_test1(X*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "map_insert_range_test1\n";
|
||||
|
||||
test::check_instances check_;
|
||||
|
||||
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME X::key_type,
|
||||
@ -827,8 +901,6 @@ void map_insert_range_test1(X*, test::random_generator generator)
|
||||
template <class X>
|
||||
void map_insert_range_test2(X*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "map_insert_range_test2\n";
|
||||
|
||||
test::check_instances check_;
|
||||
|
||||
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME X::key_type const,
|
||||
@ -1030,21 +1102,43 @@ struct overloaded_constructor
|
||||
|
||||
UNORDERED_AUTO_TEST(map_emplace_test)
|
||||
{
|
||||
boost::unordered_map<int, overloaded_constructor> x;
|
||||
{
|
||||
boost::unordered_map<int, overloaded_constructor, test::hash,
|
||||
test::equal_to,
|
||||
test::allocator1<std::pair<int const, overloaded_constructor> > >
|
||||
x;
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
x.emplace();
|
||||
BOOST_TEST(
|
||||
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
|
||||
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
|
||||
x.emplace();
|
||||
BOOST_TEST(x.find(0) != x.end() &&
|
||||
x.find(0)->second == overloaded_constructor());
|
||||
#endif
|
||||
|
||||
x.emplace(2, 3);
|
||||
BOOST_TEST(
|
||||
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
|
||||
x.emplace(2, 3);
|
||||
BOOST_TEST(x.find(2) != x.end() &&
|
||||
x.find(2)->second == overloaded_constructor(3));
|
||||
|
||||
x.try_emplace(5);
|
||||
BOOST_TEST(
|
||||
x.find(5) != x.end() && x.find(5)->second == overloaded_constructor());
|
||||
x.try_emplace(5);
|
||||
BOOST_TEST(x.find(5) != x.end() &&
|
||||
x.find(5)->second == overloaded_constructor());
|
||||
}
|
||||
|
||||
{
|
||||
boost::unordered_multimap<int, overloaded_constructor, test::hash,
|
||||
test::equal_to,
|
||||
test::allocator1<std::pair<int const, overloaded_constructor> > >
|
||||
x;
|
||||
|
||||
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
|
||||
x.emplace();
|
||||
BOOST_TEST(x.find(0) != x.end() &&
|
||||
x.find(0)->second == overloaded_constructor());
|
||||
#endif
|
||||
|
||||
x.emplace(2, 3);
|
||||
BOOST_TEST(x.find(2) != x.end() &&
|
||||
x.find(2)->second == overloaded_constructor(3));
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(set_emplace_test)
|
||||
@ -1052,7 +1146,7 @@ UNORDERED_AUTO_TEST(set_emplace_test)
|
||||
boost::unordered_set<overloaded_constructor> x;
|
||||
overloaded_constructor check;
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
|
||||
x.emplace();
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
#endif
|
||||
@ -1098,48 +1192,109 @@ struct convertible_to_piecewise
|
||||
|
||||
UNORDERED_AUTO_TEST(map_emplace_test2)
|
||||
{
|
||||
boost::unordered_map<overloaded_constructor, overloaded_constructor> x;
|
||||
// Emulating piecewise construction with boost::tuple bypasses the
|
||||
// allocator's construct method, but still uses test destroy method.
|
||||
test::detail::disable_construction_tracking _scoped;
|
||||
|
||||
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
|
||||
boost::make_tuple());
|
||||
BOOST_TEST(
|
||||
x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second == overloaded_constructor());
|
||||
{
|
||||
boost::unordered_map<overloaded_constructor, overloaded_constructor,
|
||||
boost::hash<overloaded_constructor>,
|
||||
std::equal_to<overloaded_constructor>,
|
||||
test::allocator1<std::pair<overloaded_constructor const,
|
||||
overloaded_constructor> > >
|
||||
x;
|
||||
|
||||
x.emplace(
|
||||
convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
|
||||
BOOST_TEST(
|
||||
x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second == overloaded_constructor());
|
||||
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
|
||||
boost::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.emplace(piecewise_rvalue(), boost::make_tuple(2, 3),
|
||||
boost::make_tuple(4, 5, 6));
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
x.emplace(convertible_to_piecewise(), boost::make_tuple(1),
|
||||
boost::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
derived_from_piecewise_construct_t d;
|
||||
x.emplace(d, boost::make_tuple(9, 3, 1), boost::make_tuple(10));
|
||||
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
|
||||
x.find(overloaded_constructor(9, 3, 1))->second ==
|
||||
overloaded_constructor(10));
|
||||
x.emplace(piecewise_rvalue(), boost::make_tuple(2, 3),
|
||||
boost::make_tuple(4, 5, 6));
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
|
||||
x.clear();
|
||||
derived_from_piecewise_construct_t d;
|
||||
x.emplace(d, boost::make_tuple(9, 3, 1), boost::make_tuple(10));
|
||||
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
|
||||
x.find(overloaded_constructor(9, 3, 1))->second ==
|
||||
overloaded_constructor(10));
|
||||
|
||||
x.try_emplace(overloaded_constructor());
|
||||
BOOST_TEST(
|
||||
x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second == overloaded_constructor());
|
||||
x.clear();
|
||||
|
||||
x.try_emplace(1);
|
||||
BOOST_TEST(
|
||||
x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second == overloaded_constructor());
|
||||
x.try_emplace(overloaded_constructor());
|
||||
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
x.try_emplace(1);
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
|
||||
x.clear();
|
||||
|
||||
x.try_emplace(x.begin(), overloaded_constructor());
|
||||
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.try_emplace(x.end(), 1);
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.try_emplace(x.begin(), overloaded_constructor(2, 3), 4, 5, 6);
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
}
|
||||
|
||||
{
|
||||
boost::unordered_multimap<overloaded_constructor,
|
||||
overloaded_constructor, boost::hash<overloaded_constructor>,
|
||||
std::equal_to<overloaded_constructor>,
|
||||
test::allocator1<std::pair<overloaded_constructor const,
|
||||
overloaded_constructor> > >
|
||||
x;
|
||||
|
||||
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
|
||||
boost::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.emplace(convertible_to_piecewise(), boost::make_tuple(1),
|
||||
boost::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.emplace(piecewise_rvalue(), boost::make_tuple(2, 3),
|
||||
boost::make_tuple(4, 5, 6));
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
|
||||
derived_from_piecewise_construct_t d;
|
||||
x.emplace(d, boost::make_tuple(9, 3, 1), boost::make_tuple(10));
|
||||
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
|
||||
x.find(overloaded_constructor(9, 3, 1))->second ==
|
||||
overloaded_constructor(10));
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(set_emplace_test2)
|
||||
@ -1158,9 +1313,171 @@ UNORDERED_AUTO_TEST(set_emplace_test2)
|
||||
boost::make_tuple(2, 3));
|
||||
check =
|
||||
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
|
||||
;
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
}
|
||||
|
||||
// Use the preprocessor to generate tests using different combinations of
|
||||
// boost/std piecewise_construct_t/tuple.
|
||||
|
||||
#define PIECEWISE_TEST_NAME boost_tuple_piecewise_tests
|
||||
#define PIECEWISE_NAMESPACE boost::unordered
|
||||
#define TUPLE_NAMESPACE boost
|
||||
#define EMULATING_PIECEWISE_CONSTRUCTION 1
|
||||
#include "./insert_tests.cpp"
|
||||
|
||||
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
|
||||
|
||||
#define PIECEWISE_TEST_NAME boost_tuple_std_piecewise_tests
|
||||
#define PIECEWISE_NAMESPACE std
|
||||
#define TUPLE_NAMESPACE boost
|
||||
#define EMULATING_PIECEWISE_CONSTRUCTION 1
|
||||
#include "./insert_tests.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
#define PIECEWISE_TEST_NAME std_tuple_boost_piecewise_tests
|
||||
#define PIECEWISE_NAMESPACE boost::unordered
|
||||
#define TUPLE_NAMESPACE std
|
||||
#define EMULATING_PIECEWISE_CONSTRUCTION 0
|
||||
#include "./insert_tests.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
|
||||
BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
|
||||
|
||||
#define PIECEWISE_TEST_NAME std_piecewise_tests
|
||||
#define PIECEWISE_NAMESPACE std
|
||||
#define TUPLE_NAMESPACE std
|
||||
#define EMULATING_PIECEWISE_CONSTRUCTION 0
|
||||
#include "./insert_tests.cpp"
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
RUN_TESTS_QUIET()
|
||||
|
||||
#else // PIECEWISE_TEST_NAME
|
||||
|
||||
UNORDERED_AUTO_TEST(PIECEWISE_TEST_NAME)
|
||||
{
|
||||
#if EMULATING_PIECEWISE_CONSTRUCTION
|
||||
test::detail::disable_construction_tracking _scoped;
|
||||
#endif
|
||||
|
||||
{
|
||||
boost::unordered_map<overloaded_constructor, overloaded_constructor,
|
||||
boost::hash<overloaded_constructor>,
|
||||
std::equal_to<overloaded_constructor>,
|
||||
test::allocator1<std::pair<overloaded_constructor const,
|
||||
overloaded_constructor> > >
|
||||
x;
|
||||
|
||||
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
|
||||
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
|
||||
TUPLE_NAMESPACE::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
|
||||
TUPLE_NAMESPACE::make_tuple(4, 5, 6));
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
|
||||
derived_from_piecewise_construct_t d;
|
||||
x.emplace(d, TUPLE_NAMESPACE::make_tuple(9, 3, 1),
|
||||
TUPLE_NAMESPACE::make_tuple(10));
|
||||
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
|
||||
x.find(overloaded_constructor(9, 3, 1))->second ==
|
||||
overloaded_constructor(10));
|
||||
|
||||
x.clear();
|
||||
|
||||
x.try_emplace(overloaded_constructor());
|
||||
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.try_emplace(1);
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
}
|
||||
{
|
||||
boost::unordered_multimap<overloaded_constructor,
|
||||
overloaded_constructor, boost::hash<overloaded_constructor>,
|
||||
std::equal_to<overloaded_constructor>,
|
||||
test::allocator1<std::pair<overloaded_constructor const,
|
||||
overloaded_constructor> > >
|
||||
x;
|
||||
|
||||
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
|
||||
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
|
||||
x.find(overloaded_constructor())->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
|
||||
TUPLE_NAMESPACE::make_tuple());
|
||||
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
|
||||
x.find(overloaded_constructor(1))->second ==
|
||||
overloaded_constructor());
|
||||
|
||||
x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
|
||||
TUPLE_NAMESPACE::make_tuple(4, 5, 6));
|
||||
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
|
||||
x.find(overloaded_constructor(2, 3))->second ==
|
||||
overloaded_constructor(4, 5, 6));
|
||||
|
||||
derived_from_piecewise_construct_t d;
|
||||
x.emplace(d, TUPLE_NAMESPACE::make_tuple(9, 3, 1),
|
||||
TUPLE_NAMESPACE::make_tuple(10));
|
||||
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
|
||||
x.find(overloaded_constructor(9, 3, 1))->second ==
|
||||
overloaded_constructor(10));
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(BOOST_PP_CAT(PIECEWISE_TEST_NAME, 2))
|
||||
{
|
||||
#if EMULATING_PIECEWISE_CONSTRUCTION
|
||||
test::detail::disable_construction_tracking _scoped;
|
||||
#endif
|
||||
|
||||
boost::unordered_set<
|
||||
std::pair<overloaded_constructor, overloaded_constructor> >
|
||||
x;
|
||||
std::pair<overloaded_constructor, overloaded_constructor> check;
|
||||
|
||||
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
|
||||
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
|
||||
x.clear();
|
||||
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
|
||||
TUPLE_NAMESPACE::make_tuple(1), TUPLE_NAMESPACE::make_tuple(2, 3));
|
||||
check =
|
||||
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
|
||||
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
|
||||
}
|
||||
|
||||
#undef PIECEWISE_TEST_NAME
|
||||
#undef PIECEWISE_NAMESPACE
|
||||
#undef TUPLE_NAMESPACE
|
||||
#undef EMULATING_PIECEWISE_CONSTRUCTION
|
||||
|
||||
#endif
|
||||
|
@ -99,7 +99,6 @@ UNORDERED_AUTO_TEST(merge_multiset)
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
UNORDERED_AUTO_TEST(merge_set_and_multiset)
|
||||
{
|
||||
boost::unordered_set<int> x;
|
||||
@ -139,14 +138,15 @@ UNORDERED_AUTO_TEST(merge_set_and_multiset)
|
||||
test::check_equivalent_keys(x);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class X> void merge_empty_test(X*, test::random_generator generator)
|
||||
template <class X1, class X2>
|
||||
void merge_empty_test(X1*, X2*, test::random_generator generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
X x1(v.begin(), v.end()), x2;
|
||||
test::random_values<X1> v(1000, generator);
|
||||
X1 x1(v.begin(), v.end());
|
||||
X2 x2;
|
||||
x1.merge(x2);
|
||||
test::check_container(x1, v);
|
||||
BOOST_TEST(x2.empty());
|
||||
@ -160,7 +160,8 @@ void merge_into_empty_test(X*, test::random_generator generator)
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> v(1000, generator);
|
||||
X x1, x2(v.begin(), v.end());
|
||||
X x1;
|
||||
X x2(v.begin(), v.end());
|
||||
x1.merge(x2);
|
||||
test::check_container(x1, v);
|
||||
BOOST_TEST(x2.empty());
|
||||
@ -168,89 +169,173 @@ void merge_into_empty_test(X*, test::random_generator generator)
|
||||
test::check_equivalent_keys(x2);
|
||||
}
|
||||
|
||||
template <class X> void unique_merge_test(X*, test::random_generator generator)
|
||||
template <class X1, class X2>
|
||||
void merge_into_unique_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
|
||||
test::random_generator generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> v1(1000, generator);
|
||||
test::random_values<X> v2(1000, generator);
|
||||
test::random_values<X1> v1(1000, generator);
|
||||
test::random_values<X2> v2(1000, generator);
|
||||
v1.insert(v2.begin(), boost::next(v2.begin(), 100));
|
||||
v2.insert(v1.begin(), boost::next(v1.begin(), 100));
|
||||
|
||||
X x1(v1.begin(), v1.end()), x2(v2.begin(), v2.end());
|
||||
x1.merge(x2);
|
||||
X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1),
|
||||
test::equal_to(hash_equal1));
|
||||
X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2),
|
||||
test::equal_to(hash_equal2));
|
||||
|
||||
test::ordered<X> tracker1 = test::create_ordered(x1);
|
||||
test::ordered<X> tracker2 = test::create_ordered(x2);
|
||||
test::ordered<X> tracker_tmp = test::create_ordered(x2);
|
||||
test::ordered<X1> tracker1 = test::create_ordered(x1);
|
||||
test::ordered<X2> tracker2 = test::create_ordered(x2);
|
||||
tracker1.insert(v1.begin(), v1.end());
|
||||
tracker_tmp.insert(v2.begin(), v2.end());
|
||||
for (BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator it =
|
||||
tracker_tmp.begin();
|
||||
it != tracker_tmp.end(); ++it) {
|
||||
for (typename X2::iterator it = x2.begin(); it != x2.end(); ++it) {
|
||||
if (!tracker1.insert(*it).second) {
|
||||
tracker2.insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
x1.merge(x2);
|
||||
|
||||
tracker1.compare(x1);
|
||||
tracker2.compare(x2);
|
||||
test::check_equivalent_keys(x1);
|
||||
test::check_equivalent_keys(x2);
|
||||
}
|
||||
|
||||
template <class X> void equiv_merge_test(X*, test::random_generator generator)
|
||||
template <class X1, class X2>
|
||||
void merge_into_equiv_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
|
||||
test::random_generator generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<X> v1(1000, generator);
|
||||
test::random_values<X> v2(1000, generator);
|
||||
test::random_values<X1> v1(1000, generator);
|
||||
test::random_values<X2> v2(1000, generator);
|
||||
v1.insert(v2.begin(), boost::next(v2.begin(), 100));
|
||||
v2.insert(v1.begin(), boost::next(v1.begin(), 100));
|
||||
|
||||
X x1(v1.begin(), v1.end()), x2(v2.begin(), v2.end());
|
||||
X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1),
|
||||
test::equal_to(hash_equal1));
|
||||
X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2),
|
||||
test::equal_to(hash_equal2));
|
||||
x1.merge(x2);
|
||||
|
||||
test::ordered<X> tracker1 = test::create_ordered(x1);
|
||||
test::ordered<X1> tracker1 = test::create_ordered(x1);
|
||||
test::ordered<X2> tracker2 = test::create_ordered(x2);
|
||||
tracker1.insert(v1.begin(), v1.end());
|
||||
tracker1.insert(v2.begin(), v2.end());
|
||||
tracker2.insert(v2.begin(), v2.end());
|
||||
tracker1.insert(tracker2.begin(), tracker2.end());
|
||||
tracker2.clear();
|
||||
|
||||
tracker1.compare(x1);
|
||||
BOOST_TEST(x2.empty());
|
||||
tracker2.compare(x2);
|
||||
test::check_equivalent_keys(x1);
|
||||
test::check_equivalent_keys(x2);
|
||||
}
|
||||
|
||||
boost::unordered_set<test::movable, test::hash, test::equal_to,
|
||||
std::allocator<test::movable> >* test_set_std_alloc;
|
||||
boost::unordered_multiset<test::movable, test::hash, test::equal_to,
|
||||
std::allocator<test::movable> >* test_multiset_std_alloc;
|
||||
|
||||
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
|
||||
std::allocator<test::object> >* test_map_std_alloc;
|
||||
boost::unordered_multimap<test::object, test::object, test::hash,
|
||||
test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
|
||||
|
||||
boost::unordered_set<test::object, test::hash, test::equal_to,
|
||||
test::allocator1<test::object> >* test_set;
|
||||
boost::unordered_multiset<test::movable, test::hash, test::equal_to,
|
||||
test::allocator2<test::movable> >* test_multiset;
|
||||
boost::unordered_multiset<test::object, test::hash, test::equal_to,
|
||||
test::allocator1<test::object> >* test_multiset;
|
||||
|
||||
boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
|
||||
test::allocator2<test::movable> >* test_map;
|
||||
boost::unordered_multimap<test::object, test::object, test::hash,
|
||||
test::equal_to, test::allocator1<test::object> >* test_multimap;
|
||||
boost::unordered_multimap<test::movable, test::movable, test::hash,
|
||||
test::equal_to, test::allocator2<test::movable> >* test_multimap;
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
|
||||
// clang-format off
|
||||
UNORDERED_TEST(merge_empty_test,
|
||||
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_multiset)(
|
||||
test_map)(test_multimap))((default_generator)(generate_collisions)))
|
||||
((test_set_std_alloc)(test_multiset_std_alloc))
|
||||
((test_set_std_alloc)(test_multiset_std_alloc))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_empty_test,
|
||||
((test_map_std_alloc)(test_multimap_std_alloc))
|
||||
((test_map_std_alloc)(test_multimap_std_alloc))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_empty_test,
|
||||
((test_set)(test_multiset))
|
||||
((test_set)(test_multiset))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_empty_test,
|
||||
((test_map)(test_multimap))
|
||||
((test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)))
|
||||
|
||||
UNORDERED_TEST(merge_into_empty_test,
|
||||
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_multiset)(
|
||||
test_map)(test_multimap))((default_generator)(generate_collisions)))
|
||||
((test_set_std_alloc)(test_multiset_std_alloc))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_empty_test,
|
||||
((test_map_std_alloc)(test_multimap_std_alloc))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_empty_test,
|
||||
((test_set)(test_multiset))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_empty_test,
|
||||
((test_map)(test_multimap))
|
||||
((default_generator)(generate_collisions)))
|
||||
|
||||
UNORDERED_TEST(unique_merge_test,
|
||||
((test_set_std_alloc)(test_set)(test_map))((default_generator)))
|
||||
UNORDERED_TEST(merge_into_unique_keys_test,
|
||||
((test_set_std_alloc))
|
||||
((test_set_std_alloc)(test_multiset_std_alloc))
|
||||
((0)(1)(2))
|
||||
((0)(1)(2))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_unique_keys_test,
|
||||
((test_map_std_alloc))
|
||||
((test_map_std_alloc)(test_multimap_std_alloc))
|
||||
((0)(1)(2))
|
||||
((0)(1)(2))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_unique_keys_test,
|
||||
((test_set))
|
||||
((test_set)(test_multiset))
|
||||
((0)(1)(2))
|
||||
((0)(1)(2))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_unique_keys_test,
|
||||
((test_map))
|
||||
((test_map)(test_multimap))
|
||||
((0)(1)(2))
|
||||
((0)(1)(2))
|
||||
((default_generator)(generate_collisions)))
|
||||
|
||||
UNORDERED_TEST(equiv_merge_test, ((test_multimap_std_alloc)(test_multiset)(
|
||||
test_multimap))((default_generator)))
|
||||
UNORDERED_TEST(merge_into_equiv_keys_test,
|
||||
((test_multiset_std_alloc))
|
||||
((test_set_std_alloc)(test_multiset_std_alloc))
|
||||
((0)(1)(2))
|
||||
((0)(1)(2))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_equiv_keys_test,
|
||||
((test_multimap_std_alloc))
|
||||
((test_map_std_alloc)(test_multimap_std_alloc))
|
||||
((0)(1)(2))
|
||||
((0)(1)(2))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_equiv_keys_test,
|
||||
((test_multiset))
|
||||
((test_set)(test_multiset))
|
||||
((0)(1)(2))
|
||||
((0)(1)(2))
|
||||
((default_generator)(generate_collisions)))
|
||||
UNORDERED_TEST(merge_into_equiv_keys_test,
|
||||
((test_multimap))
|
||||
((test_map)(test_multimap))
|
||||
((0)(1)(2))
|
||||
((0)(1)(2))
|
||||
((default_generator)(generate_collisions)))
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
|
@ -36,7 +36,8 @@ bool throwing_test_exception = false;
|
||||
void test_throw(char const* name)
|
||||
{
|
||||
if (throwing_test_exception) {
|
||||
std::cerr << "Throw exception in: " << name << std::endl;
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Throw exception in: " << name
|
||||
<< std::endl;
|
||||
throw test_exception();
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ UNORDERED_AUTO_TEST(simple_tests)
|
||||
using namespace std;
|
||||
srand(14878);
|
||||
|
||||
std::cout << "Test unordered_set.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
|
||||
boost::unordered_set<int> set;
|
||||
simple_test(set);
|
||||
|
||||
@ -102,7 +102,7 @@ UNORDERED_AUTO_TEST(simple_tests)
|
||||
set.insert(1456);
|
||||
simple_test(set);
|
||||
|
||||
std::cout << "Test unordered_multiset.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
|
||||
boost::unordered_multiset<int> multiset;
|
||||
simple_test(multiset);
|
||||
|
||||
@ -113,7 +113,7 @@ UNORDERED_AUTO_TEST(simple_tests)
|
||||
}
|
||||
simple_test(multiset);
|
||||
|
||||
std::cout << "Test unordered_map.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
|
||||
boost::unordered_map<int, int> map;
|
||||
|
||||
for (int i2 = 0; i2 < 1000; ++i2) {
|
||||
@ -121,7 +121,7 @@ UNORDERED_AUTO_TEST(simple_tests)
|
||||
}
|
||||
simple_test(map);
|
||||
|
||||
std::cout << "Test unordered_multimap.\n";
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
|
||||
boost::unordered_multimap<int, int> multimap;
|
||||
|
||||
for (int i3 = 0; i3 < 1000; ++i3) {
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "../helpers/postfix.hpp"
|
||||
// clang-format on
|
||||
|
||||
#include <iostream>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
namespace unnecessary_copy_tests {
|
||||
@ -138,32 +137,36 @@ std::size_t hash_value(unnecessary_copy_tests::count_copies const& x)
|
||||
#define COPY_COUNT(n) \
|
||||
if (::unnecessary_copy_tests::count_copies::copies != n) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr << "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: " << n << std::endl; \
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
|
||||
<< "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: " << n << std::endl; \
|
||||
}
|
||||
#define MOVE_COUNT(n) \
|
||||
if (::unnecessary_copy_tests::count_copies::moves != n) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr << "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< " expecting: " << n << std::endl; \
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
|
||||
<< "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< " expecting: " << n << std::endl; \
|
||||
}
|
||||
#define COPY_COUNT_RANGE(a, b) \
|
||||
if (::unnecessary_copy_tests::count_copies::copies < a || \
|
||||
::unnecessary_copy_tests::count_copies::copies > b) { \
|
||||
BOOST_ERROR("Wrong number of copies."); \
|
||||
std::cerr << "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
|
||||
<< "Number of copies: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::copies \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
}
|
||||
#define MOVE_COUNT_RANGE(a, b) \
|
||||
if (::unnecessary_copy_tests::count_copies::moves < a || \
|
||||
::unnecessary_copy_tests::count_copies::moves > b) { \
|
||||
BOOST_ERROR("Wrong number of moves."); \
|
||||
std::cerr << "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
|
||||
<< "Number of moves: " \
|
||||
<< ::unnecessary_copy_tests::count_copies::moves \
|
||||
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
|
||||
}
|
||||
#define COPY_COUNT_EXTRA(a, b) COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
|
||||
#define MOVE_COUNT_EXTRA(a, b) MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
|
||||
@ -180,6 +183,53 @@ template <class T> void unnecessary_copy_insert_test(T*)
|
||||
reset();
|
||||
x.insert(a);
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(0);
|
||||
}
|
||||
|
||||
template <class T> void unnecessary_copy_insert_rvalue_set_test(T*)
|
||||
{
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
reset();
|
||||
x.insert(boost::move(a));
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(1);
|
||||
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a2;
|
||||
reset();
|
||||
x.insert(boost::move(a));
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT((x.size() == 2 ? 1 : 0));
|
||||
}
|
||||
|
||||
template <class T> void unnecessary_copy_insert_rvalue_map_test(T*)
|
||||
{
|
||||
// Doesn't currently try to emulate std::pair move construction,
|
||||
// so std::pair's require a copy. Could try emulating it in
|
||||
// construct_from_args.
|
||||
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
reset();
|
||||
x.insert(boost::move(a));
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(1);
|
||||
#endif
|
||||
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a2;
|
||||
reset();
|
||||
x.insert(boost::move(a));
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT((x.size() == 2 ? 1 : 0));
|
||||
MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT((x.size() == 2 ? 1 : 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::unordered_set<count_copies>* set;
|
||||
@ -188,6 +238,8 @@ boost::unordered_map<int, count_copies>* map;
|
||||
boost::unordered_multimap<int, count_copies>* multimap;
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap)))
|
||||
UNORDERED_TEST(unnecessary_copy_insert_rvalue_set_test, ((set)(multiset)))
|
||||
UNORDERED_TEST(unnecessary_copy_insert_rvalue_map_test, ((map)(multimap)))
|
||||
|
||||
template <class T> void unnecessary_copy_emplace_test(T*)
|
||||
{
|
||||
@ -310,20 +362,15 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
|
||||
// 0 arguments
|
||||
//
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
|
||||
// The container will have to create a copy in order to compare with
|
||||
// the existing element.
|
||||
reset();
|
||||
x.emplace();
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
|
||||
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
// source_cost doesn't make much sense here, but it seems to fit.
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(source_cost);
|
||||
#else
|
||||
COPY_COUNT(1);
|
||||
MOVE_COUNT(1 + source_cost);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -347,13 +394,8 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
|
||||
// No move should take place.
|
||||
reset();
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(1);
|
||||
#endif
|
||||
|
||||
// Use a new value for cases where a did get moved...
|
||||
count_copies b;
|
||||
@ -409,7 +451,7 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
|
||||
// 0 arguments
|
||||
//
|
||||
|
||||
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
|
||||
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
|
||||
// COPY_COUNT(1) would be okay here.
|
||||
reset();
|
||||
x.emplace();
|
||||
@ -501,7 +543,7 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
|
||||
COPY_COUNT(0);
|
||||
MOVE_COUNT(0);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
|
||||
#if BOOST_UNORDERED_TUPLE_ARGS
|
||||
|
||||
reset();
|
||||
x.emplace(boost::unordered::piecewise_construct,
|
||||
|
Reference in New Issue
Block a user