Compare commits

...

65 Commits

Author SHA1 Message Date
Daniel James 8f51dc6082 Fix some test warnings.
And turn on warnings as errors in Travis.
2016-08-19 11:41:19 +01:00
Daniel James 79deac97dd Merge branch 'develop' 2016-08-17 12:11:13 +01:00
Daniel James e92f7d86c1 Remove array_constructor.
I was using SFINAE for everything because some old compilers had issues.
But that's hopefully in the distant past now.
2016-08-14 20:55:40 +01:00
Daniel James 93a33ba15f Remove a couple of unneeded includes. 2016-08-14 20:55:40 +01:00
Daniel James ad353c8e3d Move some of the includes up into allocate.hpp 2016-08-14 20:55:40 +01:00
Daniel James 09717ffca4 Remove a few unnecessary internal includes. 2016-08-14 20:55:40 +01:00
Daniel James ce4b840299 Map/set details types in individual headers. 2016-08-14 20:55:40 +01:00
Daniel James 5a8df0ebe4 Hopefully a bit more readable. 2016-08-14 20:55:40 +01:00
Daniel James 6029d1cfd0 Trim down node_tmp code. 2016-08-14 20:55:40 +01:00
Daniel James 3fe46a1769 Cleaner emplace_impl in equivalent. 2016-08-14 20:55:40 +01:00
Daniel James 5490bcfe95 Remove node_tmp overload of add_node. 2016-08-14 20:55:40 +01:00
Daniel James 078c562b6c Pull some common code into a function. 2016-08-14 20:55:40 +01:00
Daniel James 88612a8be4 Less faffing around with node_constructor. 2016-08-14 20:55:40 +01:00
Daniel James 37a6903831 Move node construction into allocate.hpp 2016-08-14 20:55:40 +01:00
Daniel James 8017d9e684 Change how node construction works.
Split node_constructor into two classes, one for constructing a node
without a value, and then another for holding it once the value is
constructed.

Do the work of constructing values in convenience functions in
allocate.hpp (construct_value_generic, construct_value, construct_pair).
2016-08-14 20:55:40 +01:00
Daniel James 609ae6cb4e Expand out fill_buckets. 2016-08-14 20:55:40 +01:00
Daniel James 603f785739 Merge branch 'develop' 2016-08-14 20:51:44 +01:00
Daniel James 992f9ccf21 Turn off memory sanitizer on travis.
It's not working at all.
2016-08-14 20:39:46 +01:00
Daniel James e250fb44f6 Merge local develop branch develop
Oops, I merged the wrong 'develop' branch into master. Luckily, there's
not much of a difference, so I'm resolving the merge here, and will
merge into master soon.
2016-08-14 20:02:13 +01:00
Daniel James 9767d86d97 Merge branch 'develop' 2016-08-14 19:59:22 +01:00
Daniel James 7687c99708 Disable clang c++03 memory sanitizer tests. 2016-08-04 13:35:48 +01:00
Daniel James 81cc773013 Try to fix mem/std11 toolset. 2016-08-04 13:35:48 +01:00
Daniel James cdb887e880 Clean up a memory leak in a test. 2016-08-04 13:35:47 +01:00
Daniel James 041fee64df Don't stop Boost.Build on error. 2016-08-04 13:35:46 +01:00
Daniel James e3dd1f276e Use clang and gcc's sanitizers in travis. 2016-08-03 14:24:52 +01:00
Daniel James 0769ecd70d Some more checks.
The intel-linux failures I'm getting now are odd. This find test is
failing for iterator, but not const_iterator. So maybe it's a problem
with the iterator object. The failures I was getting before have
disappeared, so I'm not sure about that.
2016-07-29 12:19:50 +01:00
Daniel James 2be69b3eb9 A little more information in the find_tests.
Now the intel-linux tester that was failing for erase_tests is passing,
but has started failing for find_tests instead. Oddly the test for
non-const find is failing, but the const find is fine - this doesn't
make much sense as they should be the same. Not sure, but it suggests
the problem might be in the way iterators are handled, rather than the
data structure?

Checking the iterators before checking that the keys are equal in order
to tell which part of the test is failing.
2016-07-27 06:51:05 +01:00
Daniel James bc601e34d2 More info on test failure on intel-linux.
The count check is reporting errors, but everything else appears to work
okay.
2016-07-25 15:03:39 +01:00
Daniel James 79e39d9d43 Copy build changes from the develop branch. 2016-07-03 21:36:14 +01:00
Daniel James 6bc57bd398 Typo 2016-07-03 08:46:40 +01:00
Daniel James 1bca2df642 Always explicitly specify standard for travis. 2016-07-03 08:42:25 +01:00
Daniel James 59cbe3d483 Also move exception tests into test/Jamfile.v2
Moving the tests successfully restored the test results, so do it for
the exception tests as well.
2016-07-03 08:42:17 +01:00
Daniel James 21f2522695 Try running the tests from unordered/test. 2016-07-02 22:11:43 +01:00
Daniel James 3720b0be58 Try creating a project for test.
For some reason the unordered test results are not showing up any more.
This is odd, as when I try locally they do run. I don't know why this
is, but it's possible that it's because there isn't an actual project in
the test directory, so try adding one.
2016-07-01 11:12:29 +01:00
Daniel James 413b45a62e Merge remote-tracking branch 'origin/develop' 2016-06-03 00:00:58 +01:00
Daniel James 7b8e3d01de Use argument SFINAE instead of return SFINAE 2016-06-03 00:00:51 +01:00
Daniel James b4a3c6f460 Fix exception safety in assignment for multimap/multiset.
The assignment code seemed like a bit of a premature optimization, I
replaced it with a slightly slower but much simpler implementation.
2016-05-30 15:02:04 +01:00
Daniel James 1d4845d6b8 Stop using predef in test. 2016-05-26 22:39:47 +01:00
Daniel James c26acdba15 Travis 2016-05-26 22:31:43 +01:00
Daniel James 3f42a56bae Remove old deprecated warning. 2016-05-26 09:25:10 +01:00
Daniel James 144a0c1791 Remove BOOST_NO_STD_DISTANCE workaround. 2016-05-26 09:24:25 +01:00
Daniel James cc2b1a1ef1 Stop using deprecated boost::iterator. 2016-05-26 09:24:21 +01:00
Daniel James 84dd473a5d Merge remote-tracking branch 'origin/develop' 2015-02-22 15:12:28 +00:00
Daniel James f014802eb6 Release note for pull request #4. 2015-02-22 15:08:46 +00:00
Daniel James 68eb654e7a Merge pull request #4 from tempoz/patch-2
Bounds-check after arithmetic is complete
2014-12-09 01:04:30 +00:00
Zoey Greer 3a507b4e39 Bounds-check after arithmetic is complete
double_to_size can return std::numeric_limits<size_t>max(), so we cannot add 1 to the return value of double_to_size. That addition should be done while still working with a double, as can be seen being done on line 850 of this file.
This was uncovered by Coverity, and addresses Coverity issues CID13443 and CID12664
2014-12-08 16:38:38 -05:00
Daniel James 0273ec59d7 Fix Visual C++ 9.0 workaround. 2014-12-03 18:28:40 +00:00
Daniel James 9090d87725 Restore ampersand workaround for Visual C++ 9 2014-11-16 10:01:29 +00:00
Daniel James 8ccde2e5a1 Move the allocators after copying the hash functions.
Just in case the hash functions throw.
2014-11-09 23:44:16 +00:00
Daniel James 31211a607f Remove assertion that used moved allocator. Fixes #10777. 2014-11-09 23:35:35 +00:00
Daniel James 56ab93d296 Merge pull request #3 from awulkiew/fix/iterators
Remove template patameters from friend declarations in interator.
2014-11-09 15:14:02 +00:00
Adam Wulkiewicz 1d8855da27 Remove template patameters from friend declarations in interator<>. 2014-11-09 13:36:27 +01:00
Daniel James df5a7538b1 Changelog 2014-11-08 22:22:12 +00:00
Daniel James 0cedaf7ad6 Rename iterator typedef to n_iterator. 2014-11-08 22:22:11 +00:00
Daniel James b4795f414d Remove unneeded ConstNodePointer template parameters. 2014-11-08 22:22:11 +00:00
Daniel James 2c9d209eef Remove incorrect changelog note.
A minor change that is not actually in this release, will be in the next one.
Probably too late to rebuild the documenation.
2014-11-02 17:35:05 +00:00
Daniel James a81c86a90e Remove use of operator&.
Also reactivate operator& for minimal test classes. Apparently I
disabled them because of a problem in a type trait, but I'm not seeing
that now. Maybe it will appear on other compilers.
2014-10-26 22:21:12 +00:00
Daniel James bf0f90ff03 Merge branch 'develop' 2014-10-26 12:18:38 +00:00
Daniel James 7c6f1ef227 Changelog 2014-10-26 12:17:58 +00:00
Daniel James 99985bb1b2 Fix pointer types in iterators.
https://svn.boost.org/trac/boost/ticket/10672
2014-10-22 22:03:32 +01:00
Zoey Greer 8c5aa5086d Initialize data_ in value_base default constructor
This means data_ should get initialized in the default constructor for boost::unordered::detail::unique_node (and any other inheritors), as this constructor will be called there.

This uninitialized data member was reported by Coverity (CID 49445), which unfortunately does not seem to have any convenient way to publicly, globally address issues.
2014-10-22 21:27:27 +01:00
Daniel James b1232d8061 Revert some changes so that I can merge to master.
Revert "Rename iterator typedef to n_iterator." and "Combine some of the
headers."

This reverts commits: 2f6b81d8c1 and
e1b39bbbfb.
2014-10-22 21:24:36 +01:00
Daniel James 2f6b81d8c1 Rename iterator typedef to n_iterator. 2014-08-19 16:41:10 +01:00
Daniel James e1b39bbbfb Combine some of the headers. 2014-08-19 16:41:10 +01:00
Daniel James 6b7cecb9d3 Workaround initialiser list bug in gcc 4.4. 2014-08-02 03:11:44 +01:00
34 changed files with 977 additions and 785 deletions
+38
View File
@@ -0,0 +1,38 @@
# Copyright (C) 2016 Daniel James.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# Use Trusty to get a reasonably recent version of Boost.
sudo: required
dist: trusty
language: c++
addons:
apt:
packages:
- libboost-dev
- libboost-tools-dev
matrix:
include:
- compiler: gcc
env: BJAM_TOOLSET=gcc
- compiler: gcc
env: BJAM_TOOLSET=gcc-std11
- compiler: clang
env: BJAM_TOOLSET=clang
- compiler: clang
env: BJAM_TOOLSET=clang-std11
before_script:
- |
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 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
- cat ~/user-config.jam
- touch Jamroot.jam
script:
- cd test && bjam ${BJAM_TOOLSET} include=${TRAVIS_BUILD_DIR}/include
+27
View File
@@ -252,4 +252,31 @@ C++11 support has resulted in some breaking changes:
uses slower ([ticket 9282]).
* Only construct elements using allocators, as specified in C++11 standard.
[h2 Boost 1.57.0]
* Fix the `pointer` typedef in iterators ([ticket 10672]).
* Fix Coverity warning
([@https://github.com/boostorg/unordered/pull/2 GitHub #2]).
[h2 Boost 1.58.0]
* Remove unnecessary template parameter from const iterators.
* Rename private `iterator` typedef in some iterator classes, as it
confuses some traits classes.
* Fix move assignment with stateful, propagate_on_container_move_assign
allocators ([ticket 10777]).
* Fix rare exception safety issue in move assignment.
* Fix potential overflow when calculating number of buckets to allocate
([@https://github.com/boostorg/unordered/pull/4 GitHub #4]).
[h2 Boost 1.62.0]
* Remove use of deprecated `boost::iterator`.
* Remove `BOOST_NO_STD_DISTANCE` workaround.
* Remove `BOOST_UNORDERED_DEPRECATED_EQUALITY` warning.
* Simpler implementation of assignment, fixes an exception safety issue
for `unordered_multiset` and `unordered_multimap`. Might be a little slower.
* Stop using return value SFINAE which some older compilers have issues
with.
[endsect]
+180 -52
View File
@@ -14,23 +14,31 @@
#pragma once
#endif
// Some of these includes are required for other detail headers.
#include <boost/unordered/detail/fwd.hpp>
#include <boost/move/move.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/dec.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/select_type.hpp>
#include <boost/swap.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <iterator>
#include <utility>
#include <cmath>
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
#include <tuple>
@@ -808,6 +816,18 @@ namespace boost { namespace unordered { namespace detail { namespace func {
# endif
#else
template <typename Alloc, typename T>
inline void call_construct(Alloc&, T* address)
{
new ((void*) address) T();
}
template <typename Alloc, typename T, typename A0>
inline void call_construct(Alloc&, T* address,
BOOST_FWD_REF(A0) a0)
{
new ((void*) address) T(boost::forward<A0>(a0));
}
template <typename Alloc, typename T>
inline void destroy_value_impl(Alloc&, T* x) {
@@ -1053,74 +1073,182 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//
// array_constructor
//
// Allocate and construct an array in an exception safe manner, and
// clean up if an exception is thrown before the container takes charge
// of it.
// Node construction
template <typename Allocator>
struct array_constructor
template <typename NodeAlloc>
struct node_constructor
{
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
typedef typename traits::pointer pointer;
typedef NodeAlloc node_allocator;
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::value_type node;
typedef typename node_allocator_traits::pointer node_pointer;
typedef typename node::value_type value_type;
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
node_allocator& alloc_;
node_pointer node_;
bool node_constructed_;
array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
node_constructor(node_allocator& n) :
alloc_(n),
node_(),
node_constructed_(false)
{
constructed_ = pointer();
ptr_ = pointer();
}
~array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p) {
boost::unordered::detail::func::destroy(
boost::addressof(*p));
}
~node_constructor();
traits::deallocate(alloc_, ptr_, length_);
}
}
void create_node();
template <typename V>
void construct(V const& v, std::size_t l)
// no throw
node_pointer release()
{
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = traits::allocate(alloc_, length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_) {
new ((void*) boost::addressof(*constructed_)) V(v);
}
}
pointer get() const
{
return ptr_;
}
pointer release()
{
pointer p(ptr_);
ptr_ = pointer();
BOOST_ASSERT(node_ && node_constructed_);
node_pointer p = node_;
node_ = node_pointer();
return p;
}
private:
void reclaim(node_pointer p) {
BOOST_ASSERT(!node_);
node_ = p;
node_constructed_ = true;
boost::unordered::detail::func::destroy_value_impl(alloc_,
node_->value_ptr());
}
array_constructor(array_constructor const&);
array_constructor& operator=(array_constructor const&);
private:
node_constructor(node_constructor const&);
node_constructor& operator=(node_constructor const&);
};
template <typename Alloc>
node_constructor<Alloc>::~node_constructor()
{
if (node_) {
if (node_constructed_) {
boost::unordered::detail::func::destroy(
boost::addressof(*node_));
}
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
template <typename Alloc>
void node_constructor<Alloc>::create_node()
{
BOOST_ASSERT(!node_);
node_constructed_ = false;
node_ = node_allocator_traits::allocate(alloc_, 1);
new ((void*) boost::addressof(*node_)) node();
node_->init(node_);
node_constructed_ = true;
}
template <typename NodeAlloc>
struct node_tmp
{
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::pointer node_pointer;
NodeAlloc& alloc_;
node_pointer node_;
explicit node_tmp(node_pointer n, NodeAlloc& a):
alloc_(a),
node_(n)
{
}
~node_tmp();
// no throw
node_pointer release()
{
node_pointer p = node_;
node_ = node_pointer();
return p;
}
};
template <typename Alloc>
node_tmp<Alloc>::~node_tmp()
{
if (node_) {
boost::unordered::detail::func::destroy_value_impl(alloc_,
node_->value_ptr());
boost::unordered::detail::func::destroy(
boost::addressof(*node_));
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
}}}
namespace boost { namespace unordered { namespace detail { namespace func {
// Some nicer construct_value functions, might try to
// improve implementation later.
template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_value_generic(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor<Alloc> a(alloc);
a.create_node();
construct_value_impl(alloc, a.node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_FORWARD);
return a.release();
}
template <typename Alloc, typename U>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_value(Alloc& alloc, BOOST_FWD_REF(U) x)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(
alloc, a.node_->value_ptr(), boost::forward<U>(x));
return a.release();
}
// TODO: When possible, it might be better to use std::pair's
// constructor for std::piece_construct with std::tuple.
template <typename Alloc, typename Key>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(
alloc, boost::addressof(a.node_->value_ptr()->first),
boost::forward<Key>(k));
boost::unordered::detail::func::call_construct(
alloc, boost::addressof(a.node_->value_ptr()->second));
return a.release();
}
template <typename Alloc, typename Key, typename Mapped>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(
alloc, boost::addressof(a.node_->value_ptr()->first),
boost::forward<Key>(k));
boost::unordered::detail::func::call_construct(
alloc, boost::addressof(a.node_->value_ptr()->second),
boost::forward<Mapped>(m));
return a.release();
}
}}}}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
+74 -191
View File
@@ -14,14 +14,6 @@
#include <boost/unordered/detail/util.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/swap.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/iterator.hpp>
namespace boost { namespace unordered { namespace detail {
@@ -45,9 +37,9 @@ namespace boost { namespace unordered { namespace iterator_detail {
// all no throw
template <typename Node> struct iterator;
template <typename Node, typename ConstNodePointer> struct c_iterator;
template <typename Node> struct c_iterator;
template <typename Node, typename Policy> struct l_iterator;
template <typename Node, typename ConstNodePointer, typename Policy>
template <typename Node, typename Policy>
struct cl_iterator;
// Local Iterators
@@ -56,20 +48,20 @@ namespace boost { namespace unordered { namespace iterator_detail {
template <typename Node, typename Policy>
struct l_iterator
: public boost::iterator<
: public std::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::node_pointer,
typename Node::value_type*,
typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename Node2, typename ConstNodePointer, typename Policy2>
template <typename Node2, typename Policy2>
friend struct boost::unordered::iterator_detail::cl_iterator;
private:
#endif
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@@ -80,7 +72,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
l_iterator() BOOST_NOEXCEPT : ptr_() {}
l_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
l_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
value_type& operator*() const {
@@ -114,13 +106,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
};
template <typename Node, typename ConstNodePointer, typename Policy>
template <typename Node, typename Policy>
struct cl_iterator
: public boost::iterator<
: public std::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
ConstNodePointer,
typename Node::value_type const*,
typename Node::value_type const&>
{
friend struct boost::unordered::iterator_detail::l_iterator
@@ -128,7 +120,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@@ -139,7 +131,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
cl_iterator() BOOST_NOEXCEPT : ptr_() {}
cl_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
cl_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
@@ -184,19 +176,19 @@ namespace boost { namespace unordered { namespace iterator_detail {
template <typename Node>
struct iterator
: public boost::iterator<
: public std::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::node_pointer,
typename Node::value_type*,
typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename, typename>
template <typename>
friend struct boost::unordered::iterator_detail::c_iterator;
template <typename, typename>
friend struct boost::unordered::iterator_detail::l_iterator;
template <typename, typename, typename>
template <typename, typename>
friend struct boost::unordered::iterator_detail::cl_iterator;
template <typename>
friend struct boost::unordered::detail::table;
@@ -223,7 +215,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
value_type* operator->() const {
return &node_->value();
return node_->value_ptr();
}
iterator& operator++() {
@@ -246,13 +238,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
};
template <typename Node, typename ConstNodePointer>
template <typename Node>
struct c_iterator
: public boost::iterator<
: public std::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
ConstNodePointer,
typename Node::value_type const*,
typename Node::value_type const&>
{
friend struct boost::unordered::iterator_detail::iterator<Node>;
@@ -268,7 +260,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
#endif
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
node_pointer node_;
public:
@@ -280,14 +272,14 @@ namespace boost { namespace unordered { namespace iterator_detail {
explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
node_(static_cast<node_pointer>(x)) {}
c_iterator(iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
value_type const& operator*() const {
return node_->value();
}
value_type const* operator->() const {
return &node_->value();
return node_->value_ptr();
}
c_iterator& operator++() {
@@ -317,124 +309,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
namespace boost { namespace unordered { namespace detail {
///////////////////////////////////////////////////////////////////
//
// Node construction
template <typename NodeAlloc>
struct node_constructor
{
private:
typedef NodeAlloc node_allocator;
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
typedef typename node_allocator_traits::value_type node;
typedef typename node_allocator_traits::pointer node_pointer;
typedef typename node::value_type value_type;
protected:
node_allocator& alloc_;
node_pointer node_;
bool node_constructed_;
bool value_constructed_;
public:
node_constructor(node_allocator& n) :
alloc_(n),
node_(),
node_constructed_(false),
value_constructed_(false)
{
}
~node_constructor();
void construct();
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
{
construct();
boost::unordered::detail::func::construct_value_impl(
alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
value_constructed_ = true;
}
template <typename A0>
void construct_with_value2(BOOST_FWD_REF(A0) a0)
{
construct();
boost::unordered::detail::func::construct_value_impl(
alloc_, node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
value_constructed_ = true;
}
value_type const& value() const {
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
return node_->value();
}
// no throw
node_pointer release()
{
BOOST_ASSERT(node_ && node_constructed_);
node_pointer p = node_;
node_ = node_pointer();
return p;
}
private:
node_constructor(node_constructor const&);
node_constructor& operator=(node_constructor const&);
};
template <typename Alloc>
node_constructor<Alloc>::~node_constructor()
{
if (node_) {
if (value_constructed_) {
boost::unordered::detail::func::destroy_value_impl(alloc_,
node_->value_ptr());
}
if (node_constructed_) {
boost::unordered::detail::func::destroy(
boost::addressof(*node_));
}
node_allocator_traits::deallocate(alloc_, node_, 1);
}
}
template <typename Alloc>
void node_constructor<Alloc>::construct()
{
if(!node_) {
node_constructed_ = false;
value_constructed_ = false;
node_ = node_allocator_traits::allocate(alloc_, 1);
new ((void*) boost::addressof(*node_)) node();
node_->init(node_);
node_constructed_ = true;
}
else {
BOOST_ASSERT(node_constructed_);
if (value_constructed_)
{
boost::unordered::detail::func::destroy_value_impl(alloc_,
node_->value_ptr());
value_constructed_ = false;
}
}
}
///////////////////////////////////////////////////////////////////
//
// Node Holder
@@ -442,11 +316,9 @@ namespace boost { namespace unordered { namespace detail {
// Temporary store for nodes. Deletes any that aren't used.
template <typename NodeAlloc>
struct node_holder : private node_constructor<NodeAlloc>
struct node_holder
{
private:
typedef node_constructor<NodeAlloc> base;
typedef NodeAlloc node_allocator;
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
@@ -456,13 +328,14 @@ namespace boost { namespace unordered { namespace detail {
typedef typename node::link_pointer link_pointer;
typedef boost::unordered::iterator_detail::iterator<node> iterator;
node_constructor<NodeAlloc> constructor_;
node_pointer nodes_;
public:
template <typename Table>
explicit node_holder(Table& b) :
base(b.node_alloc()),
constructor_(b.node_alloc()),
nodes_()
{
if (b.size_) {
@@ -475,61 +348,71 @@ namespace boost { namespace unordered { namespace detail {
~node_holder();
void node_for_assignment()
node_pointer pop_node()
{
if (!this->node_ && nodes_) {
this->node_ = nodes_;
nodes_ = static_cast<node_pointer>(nodes_->next_);
this->node_->init(this->node_);
this->node_->next_ = link_pointer();
this->node_constructed_ = true;
this->value_constructed_ = true;
}
node_pointer n = nodes_;
nodes_ = static_cast<node_pointer>(nodes_->next_);
n->init(n);
n->next_ = link_pointer();
return n;
}
template <typename T>
inline void assign_impl(T const& v) {
if (this->node_ && this->value_constructed_) {
this->node_->value() = v;
inline node_pointer copy_of(T const& v) {
if (nodes_) {
node_tmp<NodeAlloc> a(pop_node(), constructor_.alloc_);
a.node_->value() = v;
return a.release();
}
else {
this->construct_with_value2(v);
constructor_.create_node();
boost::unordered::detail::func::call_construct(
constructor_.alloc_, constructor_.node_->value_ptr(), v);
return constructor_.release();
}
}
template <typename T1, typename T2>
inline void assign_impl(std::pair<T1 const, T2> const& v) {
this->construct_with_value2(v);
inline node_pointer copy_of(std::pair<T1 const, T2> const& v) {
if (nodes_) {
constructor_.reclaim(pop_node());
}
else {
constructor_.create_node();
}
boost::unordered::detail::func::call_construct(
constructor_.alloc_, constructor_.node_->value_ptr(), v);
return constructor_.release();
}
template <typename T>
inline void move_assign_impl(T& v) {
if (this->node_ && this->value_constructed_) {
this->node_->value() = boost::move(v);
inline node_pointer move_copy_of(T& v) {
if (nodes_) {
node_tmp<NodeAlloc> a(pop_node(), constructor_.alloc_);
a.node_->value() = boost::move(v);
return a.release();
}
else {
this->construct_with_value2(boost::move(v));
constructor_.create_node();
boost::unordered::detail::func::call_construct(
constructor_.alloc_, constructor_.node_->value_ptr(),
boost::move(v));
return constructor_.release();
}
}
template <typename T1, typename T2>
inline void move_assign_impl(std::pair<T1 const, T2>& v) {
this->construct_with_value2(boost::move(v));
}
node_pointer copy_of(value_type const& v)
{
node_for_assignment();
assign_impl(v);
return base::release();
}
node_pointer move_copy_of(value_type& v)
{
node_for_assignment();
move_assign_impl(v);
return base::release();
inline node_pointer move_copy_of(std::pair<T1 const, T2>& v) {
if (nodes_) {
constructor_.reclaim(pop_node());
}
else {
constructor_.create_node();
}
boost::unordered::detail::func::call_construct(
constructor_.alloc_, constructor_.node_->value_ptr(),
boost::move(v));
return constructor_.release();
}
iterator begin() const
@@ -545,10 +428,10 @@ namespace boost { namespace unordered { namespace detail {
node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_);
boost::unordered::detail::func::destroy_value_impl(this->alloc_,
boost::unordered::detail::func::destroy_value_impl(constructor_.alloc_,
p->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*p));
node_allocator_traits::deallocate(this->alloc_, p, 1);
node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
}
}
+80 -97
View File
@@ -12,7 +12,6 @@
#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
namespace boost { namespace unordered { namespace detail {
@@ -130,55 +129,6 @@ namespace boost { namespace unordered { namespace detail {
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename T, typename H, typename P>
struct multiset
{
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
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;
};
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 A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
};
template <typename Types>
struct grouped_table_impl : boost::unordered::detail::table<Types>
{
@@ -195,6 +145,7 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::key_equal key_equal;
typedef typename table::key_type key_type;
typedef typename table::node_constructor node_constructor;
typedef typename table::node_tmp node_tmp;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
@@ -381,11 +332,10 @@ namespace boost { namespace unordered { namespace detail {
}
inline iterator add_node(
node_constructor& a,
node_pointer n,
std::size_t key_hash,
iterator pos)
{
node_pointer n = a.release();
n->hash_ = key_hash;
if (pos.node_) {
this->add_after_node(n, pos.node_);
@@ -425,23 +375,23 @@ namespace boost { namespace unordered { namespace detail {
return iterator(n);
}
iterator emplace_impl(node_constructor& a)
iterator emplace_impl(node_pointer n)
{
key_type const& k = this->get_key(a.value());
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return this->add_node(a, key_hash, position);
return this->add_node(a.release(), key_hash, position);
}
void emplace_impl_no_rehash(node_constructor& a)
void emplace_impl_no_rehash(node_pointer n)
{
key_type const& k = this->get_key(a.value());
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k);
this->add_node(a, key_hash, this->find_node(key_hash, k));
iterator position = this->find_node(key_hash, k);
this->add_node(a.release(), key_hash, position);
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -465,10 +415,9 @@ namespace boost { namespace unordered { namespace detail {
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return iterator(emplace_impl(a));
return iterator(emplace_impl(
boost::unordered::detail::func::construct_value_generic(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
////////////////////////////////////////////////////////////////////////
@@ -477,37 +426,37 @@ namespace boost { namespace unordered { namespace detail {
// if hash function throws, or inserting > 1 element, basic exception
// safety. Strong otherwise
template <class I>
typename boost::unordered::detail::enable_if_forward<I, void>::type
insert_range(I i, I j)
void insert_range(I i, I j, typename
boost::unordered::detail::enable_if_forward<I, void*>::type = 0)
{
if(i == j) return;
std::size_t distance = boost::unordered::detail::distance(i, j);
std::size_t distance = std::distance(i, j);
if(distance == 1) {
node_constructor a(this->node_alloc());
a.construct_with_value2(*i);
emplace_impl(a);
emplace_impl(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *i));
}
else {
// Only require basic exception safety here
this->reserve_for_insert(this->size_ + distance);
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
a.construct_with_value2(*i);
emplace_impl_no_rehash(a);
emplace_impl_no_rehash(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *i));
}
}
}
template <class I>
typename boost::unordered::detail::disable_if_forward<I, void>::type
insert_range(I i, I j)
void insert_range(I i, I j, typename
boost::unordered::detail::disable_if_forward<I, void*>::type = 0)
{
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
a.construct_with_value2(*i);
emplace_impl(a);
emplace_impl(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *i));
}
}
@@ -621,31 +570,65 @@ namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////
// fill_buckets
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
link_pointer prev = dst.get_previous_start();
void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
while (n.node_) {
for (iterator n = src.begin(); n.node_;) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
node_pointer first_node = creator.create(*n);
node_pointer end = first_node;
first_node->hash_ = key_hash;
prev->next_ = first_node;
++dst.size_;
iterator pos = this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *n), key_hash, iterator());
for (++n; n != group_end; ++n)
{
end = creator.create(*n);
end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *n), key_hash, pos);
}
}
}
prev = place_in_bucket(dst, prev, end);
void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for (iterator n = src.begin(); n.node_;) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
iterator pos = this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), boost::move(*n)), key_hash, iterator());
for (++n; n != group_end; ++n)
{
this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), boost::move(*n)), key_hash, pos);
}
}
}
void assign_buckets(table const& src) {
node_holder<node_allocator> holder(*this);
for (iterator n = src.begin(); n.node_;) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
iterator pos = this->add_node(holder.copy_of(*n), key_hash, iterator());
for (++n; n != group_end; ++n)
{
this->add_node(holder.copy_of(*n), key_hash, pos);
}
}
}
void move_assign_buckets(table& src) {
node_holder<node_allocator> holder(*this);
for (iterator n = src.begin(); n.node_;) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
iterator pos = this->add_node(holder.move_copy_of(*n), key_hash, iterator());
for (++n; n != group_end; ++n)
{
this->add_node(holder.move_copy_of(*n), key_hash, pos);
}
}
}
+61
View File
@@ -0,0 +1,61 @@
// Copyright (C) 2005-2016 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/unordered_map_fwd.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
namespace boost { namespace unordered { namespace detail {
template <typename A, typename K, typename M, typename H, typename P>
struct map
{
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<allocator>
traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
};
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 A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
};
}}}
+57
View File
@@ -0,0 +1,57 @@
// Copyright (C) 2005-2016 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered/unordered_set_fwd.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
namespace boost { namespace unordered { namespace detail {
template <typename A, typename T, typename H, typename P>
struct set
{
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
};
template <typename A, typename T, typename H, typename P>
struct multiset
{
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
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;
};
}}}
+71 -141
View File
@@ -13,28 +13,12 @@
#endif
#include <boost/unordered/detail/buckets.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <cmath>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4127) // conditional expression is constant
#endif
#if defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
#if defined(__EDG__)
#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
#pragma message("Warning: BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported.")
#elif defined(__GNUC__) || defined(__HP_aCC) || \
defined(__SUNPRO_CC) || defined(__IBMCPP__)
#warning "BOOST_UNORDERED_DEPRECATED_EQUALITY is no longer supported."
#endif
#endif
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
@@ -59,6 +43,10 @@ namespace boost { namespace unordered { namespace detail {
sizeof(value_type),
boost::alignment_of<value_type>::value>::type data_;
value_base() :
data_()
{}
void* address() {
return this;
}
@@ -76,70 +64,6 @@ namespace boost { namespace unordered { namespace detail {
value_base& operator=(value_base const&);
};
template <typename NodeAlloc>
struct copy_nodes
{
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
node_constructor<NodeAlloc> constructor;
explicit copy_nodes(NodeAlloc& a) : constructor(a) {}
typename node_allocator_traits::pointer create(
typename node_allocator_traits::value_type::value_type const& v)
{
constructor.construct_with_value2(v);
return constructor.release();
}
};
template <typename NodeAlloc>
struct move_nodes
{
typedef boost::unordered::detail::allocator_traits<NodeAlloc>
node_allocator_traits;
node_constructor<NodeAlloc> constructor;
explicit move_nodes(NodeAlloc& a) : constructor(a) {}
typename node_allocator_traits::pointer create(
typename node_allocator_traits::value_type::value_type& v)
{
constructor.construct_with_value2(boost::move(v));
return constructor.release();
}
};
template <typename Buckets>
struct assign_nodes
{
node_holder<typename Buckets::node_allocator> holder;
explicit assign_nodes(Buckets& b) : holder(b) {}
typename Buckets::node_pointer create(
typename Buckets::value_type const& v)
{
return holder.copy_of(v);
}
};
template <typename Buckets>
struct move_assign_nodes
{
node_holder<typename Buckets::node_allocator> holder;
explicit move_assign_nodes(Buckets& b) : holder(b) {}
typename Buckets::node_pointer create(
typename Buckets::value_type& v)
{
return holder.move_copy_of(v);
}
};
template <typename Types>
struct table :
boost::unordered::detail::functions<
@@ -183,15 +107,17 @@ namespace boost { namespace unordered { namespace detail {
bucket_pointer;
typedef boost::unordered::detail::node_constructor<node_allocator>
node_constructor;
typedef boost::unordered::detail::node_tmp<node_allocator>
node_tmp;
typedef boost::unordered::iterator_detail::
iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node, const_node_pointer> c_iterator;
c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, const_node_pointer, policy> cl_iterator;
cl_iterator<node, policy> cl_iterator;
////////////////////////////////////////////////////////////////////////
// Members
@@ -339,7 +265,7 @@ namespace boost { namespace unordered { namespace detail {
return policy::new_bucket_count(
boost::unordered::detail::double_to_size(floor(
static_cast<double>(size) /
static_cast<double>(mlf_))) + 1);
static_cast<double>(mlf_)) + 1));
}
////////////////////////////////////////////////////////////////////////
@@ -399,9 +325,7 @@ namespace boost { namespace unordered { namespace detail {
void init(table const& x)
{
if (x.size_) {
create_buckets(bucket_count_);
copy_nodes<node_allocator> node_creator(node_alloc());
table_impl::fill_buckets(x.begin(), *this, node_creator);
static_cast<table_impl*>(this)->copy_buckets(x);
}
}
@@ -412,11 +336,7 @@ namespace boost { namespace unordered { namespace detail {
}
else if(x.size_) {
// TODO: Could pick new bucket size?
create_buckets(bucket_count_);
move_nodes<node_allocator> node_creator(node_alloc());
node_holder<node_allocator> nodes(x);
table_impl::fill_buckets(nodes.begin(), *this, node_creator);
static_cast<table_impl*>(this)->move_buckets(x);
}
}
@@ -425,34 +345,53 @@ namespace boost { namespace unordered { namespace detail {
void create_buckets(std::size_t new_count)
{
boost::unordered::detail::array_constructor<bucket_allocator>
constructor(bucket_alloc());
// Creates an extra bucket to act as the start node.
constructor.construct(bucket(), new_count + 1);
std::size_t length = new_count + 1;
bucket_pointer new_buckets = bucket_allocator_traits::allocate(
bucket_alloc(), length);
bucket_pointer constructed = new_buckets;
if (buckets_)
{
// Copy the nodes to the new buckets, including the dummy
// node if there is one.
(constructor.get() +
static_cast<std::ptrdiff_t>(new_count))->next_ =
(buckets_ + static_cast<std::ptrdiff_t>(
bucket_count_))->next_;
destroy_buckets();
}
else if (bucket::extra_node)
{
node_constructor a(node_alloc());
a.construct();
BOOST_TRY {
bucket_pointer end = new_buckets
+ static_cast<std::ptrdiff_t>(length);
for(; constructed != end; ++constructed) {
new ((void*) boost::addressof(*constructed)) bucket();
}
(constructor.get() +
static_cast<std::ptrdiff_t>(new_count))->next_ =
a.release();
if (buckets_)
{
// Copy the nodes to the new buckets, including the dummy
// node if there is one.
(new_buckets +
static_cast<std::ptrdiff_t>(new_count))->next_ =
(buckets_ + static_cast<std::ptrdiff_t>(
bucket_count_))->next_;
destroy_buckets();
}
else if (bucket::extra_node)
{
node_constructor a(node_alloc());
a.create_node();
(new_buckets +
static_cast<std::ptrdiff_t>(new_count))->next_ =
a.release();
}
}
BOOST_CATCH(...) {
for(bucket_pointer p = new_buckets; p != constructed; ++p) {
boost::unordered::detail::func::destroy(
boost::addressof(*p));
}
bucket_allocator_traits::deallocate(bucket_alloc(),
new_buckets, length);
BOOST_RETHROW;
}
BOOST_CATCH_END
bucket_count_ = new_count;
buckets_ = constructor.release();
buckets_ = new_buckets;
recalculate_max_load();
}
@@ -496,9 +435,11 @@ namespace boost { namespace unordered { namespace detail {
op2.commit();
}
// Only call with nodes allocated with the currect allocator, or
// one that is equal to it. (Can't assert because other's
// allocators might have already been moved).
void move_buckets_from(table& other)
{
BOOST_ASSERT(node_alloc() == other.node_alloc());
BOOST_ASSERT(!buckets_);
buckets_ = other.buckets_;
bucket_count_ = other.bucket_count_;
@@ -656,11 +597,7 @@ namespace boost { namespace unordered { namespace detail {
clear_buckets();
}
// assign_nodes takes ownership of the container's elements,
// assigning to them if possible, and deleting any that are
// left over.
assign_nodes<table> node_creator(*this);
table_impl::fill_buckets(x.begin(), *this, node_creator);
static_cast<table_impl*>(this)->assign_buckets(x);
}
void assign(table const& x, true_type)
@@ -685,9 +622,7 @@ namespace boost { namespace unordered { namespace detail {
// Finally copy the elements.
if (x.size_) {
create_buckets(bucket_count_);
copy_nodes<node_allocator> node_creator(node_alloc());
table_impl::fill_buckets(x.begin(), *this, node_creator);
static_cast<table_impl*>(this)->copy_buckets(x);
}
}
}
@@ -706,15 +641,25 @@ namespace boost { namespace unordered { namespace detail {
void move_assign(table& x, true_type)
{
delete_buckets();
set_hash_functions new_func_this(*this, x);
allocators_.move_assign(x.allocators_);
move_assign_no_alloc(x);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
}
void move_assign(table& x, false_type)
{
if (node_alloc() == x.node_alloc()) {
delete_buckets();
move_assign_no_alloc(x);
set_hash_functions new_func_this(*this, x);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
}
else {
set_hash_functions new_func_this(*this, x);
@@ -731,24 +676,9 @@ namespace boost { namespace unordered { namespace detail {
clear_buckets();
}
// move_assign_nodes takes ownership of the container's
// elements, assigning to them if possible, and deleting
// any that are left over.
move_assign_nodes<table> node_creator(*this);
node_holder<node_allocator> nodes(x);
table_impl::fill_buckets(nodes.begin(), *this, node_creator);
static_cast<table_impl*>(this)->move_assign_buckets(x);
}
}
void move_assign_no_alloc(table& x)
{
set_hash_functions new_func_this(*this, x);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
}
// Accessors
+94 -116
View File
@@ -12,7 +12,6 @@
#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
@@ -126,54 +125,6 @@ namespace boost { namespace unordered { namespace detail {
typedef typename pick::link_pointer link_pointer;
};
template <typename A, typename T, typename H, typename P>
struct set
{
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
struct map
{
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef boost::unordered::detail::allocator_traits<allocator>
traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
};
template <typename Types>
struct table_impl : boost::unordered::detail::table<Types>
{
@@ -190,6 +141,7 @@ namespace boost { namespace unordered { namespace detail {
typedef typename table::key_equal key_equal;
typedef typename table::key_type key_type;
typedef typename table::node_constructor node_constructor;
typedef typename table::node_tmp node_tmp;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
@@ -308,10 +260,9 @@ namespace boost { namespace unordered { namespace detail {
// Emplace/Insert
inline iterator add_node(
node_constructor& a,
node_pointer n,
std::size_t key_hash)
{
node_pointer n = a.release();
n->hash_ = key_hash;
bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
@@ -340,23 +291,21 @@ namespace boost { namespace unordered { namespace detail {
return iterator(n);
}
inline iterator resize_and_add_node(node_pointer n, std::size_t key_hash)
{
node_tmp b(n, this->node_alloc());
this->reserve_for_insert(this->size_ + 1);
return this->add_node(b.release(), key_hash);
}
value_type& operator[](key_type const& k)
{
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return *pos;
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS3(
boost::unordered::piecewise_construct,
boost::make_tuple(k),
boost::make_tuple()));
this->reserve_for_insert(this->size_ + 1);
return *add_node(a, key_hash);
return *this->resize_and_add_node(
boost::unordered::detail::func::construct_pair(this->node_alloc(), k),
key_hash);
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -406,32 +355,17 @@ namespace boost { namespace unordered { namespace detail {
{
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return emplace_return(pos, false);
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(this->add_node(a, key_hash), true);
}
emplace_return emplace_impl_with_node(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) return emplace_return(pos, false);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(this->add_node(a, key_hash), true);
if (pos.node_) {
return emplace_return(pos, false);
}
else {
return emplace_return(
this->resize_and_add_node(
boost::unordered::detail::func::construct_value_generic(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
key_hash),
true);
}
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
@@ -439,9 +373,21 @@ namespace boost { namespace unordered { namespace detail {
{
// Don't have a key, so construct the node first in order
// to be able to lookup the position.
node_constructor a(this->node_alloc());
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return emplace_impl_with_node(a);
node_tmp b(
boost::unordered::detail::func::construct_value_generic(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
key_type const& k = this->get_key(b.node_->value());
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) {
return emplace_return(pos, false);
}
else {
return emplace_return(
this->resize_and_add_node(b.release(), key_hash),
true);
}
}
////////////////////////////////////////////////////////////////////////
@@ -460,9 +406,7 @@ namespace boost { namespace unordered { namespace detail {
template <class InputIt>
void insert_range_impl(key_type const& k, InputIt i, InputIt j)
{
node_constructor a(this->node_alloc());
insert_range_impl2(a, k, i, j);
insert_range_impl2(k, i, j);
while(++i != j) {
// Note: can't use get_key as '*i' might not be value_type - it
@@ -473,26 +417,25 @@ namespace boost { namespace unordered { namespace detail {
// key here. Could be more efficient if '*i' is expensive. Could
// be less efficient if copying the full value_type is
// expensive.
insert_range_impl2(a, extractor::extract(*i), i, j);
insert_range_impl2(extractor::extract(*i), i, j);
}
}
template <class InputIt>
void insert_range_impl2(node_constructor& a, key_type const& k,
InputIt i, InputIt j)
void insert_range_impl2(key_type const& k, InputIt i, InputIt j)
{
// No side effects in this initial code
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (!pos.node_) {
a.construct_with_value2(*i);
node_tmp b(
boost::unordered::detail::func::construct_value(this->node_alloc(), *i),
this->node_alloc());
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
// Nothing after this point can throw.
this->add_node(a, key_hash);
this->add_node(b.release(), key_hash);
}
}
@@ -502,8 +445,24 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(this->node_alloc());
do {
a.construct_with_value2(*i);
emplace_impl_with_node(a);
if (!a.node_) { a.create_node(); }
boost::unordered::detail::func::call_construct(
a.alloc_, a.node_->value_ptr(), *i);
node_tmp b(a.release(), a.alloc_);
key_type const& k = this->get_key(b.node_->value());
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) {
a.reclaim(b.release());
}
else {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
this->add_node(b.release(), key_hash);
}
} while(++i != j);
}
@@ -576,20 +535,39 @@ namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////
// fill_buckets
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for(iterator n = src.begin(); n.node_; ++n) {
this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), *n), n.node_->hash_);
}
}
void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
for(iterator n = src.begin(); n.node_; ++n) {
this->add_node(
boost::unordered::detail::func::construct_value(
this->node_alloc(), boost::move(*n)), n.node_->hash_);
}
}
void assign_buckets(table const& src)
{
link_pointer prev = dst.get_previous_start();
node_holder<node_allocator> holder(*this);
for(iterator n = src.begin(); n.node_; ++n) {
this->add_node(holder.copy_of(*n), n.node_->hash_);
}
}
while (n.node_) {
node_pointer node = creator.create(*n);
node->hash_ = n.node_->hash_;
prev->next_ = node;
++dst.size_;
++n;
prev = place_in_bucket(dst, prev);
void move_assign_buckets(table& src)
{
node_holder<node_allocator> holder(*this);
for(iterator n = src.begin(); n.node_; ++n) {
this->add_node(holder.move_copy_of(*n), n.node_->hash_);
}
}
+4 -21
View File
@@ -124,33 +124,16 @@ namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// insert_size/initial_size
#if !defined(BOOST_NO_STD_DISTANCE)
using ::std::distance;
#else
template <class ForwardIterator>
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
std::size_t x;
std::distance(i, j, x);
return x;
}
#endif
template <class I>
inline typename
boost::unordered::detail::enable_if_forward<I, std::size_t>::type
insert_size(I i, I j)
inline std::size_t insert_size(I i, I j, typename
boost::unordered::detail::enable_if_forward<I, void*>::type = 0)
{
return std::distance(i, j);
}
template <class I>
inline typename
boost::unordered::detail::disable_if_forward<I, std::size_t>::type
insert_size(I, I)
inline std::size_t insert_size(I, I, typename
boost::unordered::detail::disable_if_forward<I, void*>::type = 0)
{
return 1;
}
+1 -3
View File
@@ -15,9 +15,7 @@
#endif
#include <boost/unordered/unordered_map_fwd.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/unordered/detail/map.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
+1 -4
View File
@@ -14,10 +14,7 @@
#pragma once
#endif
#include <boost/unordered/unordered_set_fwd.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/unordered/detail/set.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
+72 -2
View File
@@ -5,5 +5,75 @@
import testing ;
build-project unordered ;
build-project exception ;
project unordered-test/unordered
: requirements
<warnings>all
<toolset>intel:<warnings>on
# Would be nice to define -Wundef, but I'm getting warnings from
# Boost.Preprocessor on trunk.
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>clang:<cxxflags>"-pedantic -Wextra -Wno-long-long"
;
#alias framework : /boost/test//boost_unit_test_framework ;
alias framework : ;
test-suite unordered
:
[ run unordered/fwd_set_test.cpp ]
[ run unordered/fwd_map_test.cpp ]
[ run unordered/allocator_traits.cpp ]
[ run unordered/minimal_allocator.cpp ]
[ run unordered/compile_set.cpp ]
[ run unordered/compile_map.cpp ]
[ run unordered/noexcept_tests.cpp ]
[ run unordered/link_test_1.cpp unordered/link_test_2.cpp ]
[ run unordered/incomplete_test.cpp ]
[ run unordered/simple_tests.cpp ]
[ run unordered/equivalent_keys_tests.cpp ]
[ run unordered/constructor_tests.cpp ]
[ run unordered/copy_tests.cpp ]
[ run unordered/move_tests.cpp ]
[ run unordered/assign_tests.cpp ]
[ run unordered/insert_tests.cpp ]
[ run unordered/insert_stable_tests.cpp ]
[ run unordered/unnecessary_copy_tests.cpp ]
[ run unordered/erase_tests.cpp ]
[ run unordered/erase_equiv_tests.cpp ]
[ run unordered/find_tests.cpp ]
[ run unordered/at_tests.cpp ]
[ run unordered/bucket_tests.cpp ]
[ run unordered/load_factor_tests.cpp ]
[ run unordered/rehash_tests.cpp ]
[ run unordered/equality_tests.cpp ]
[ run unordered/swap_tests.cpp ]
[ run unordered/compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_set ]
[ run unordered/compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_map ]
[ run unordered/copy_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_copy ]
[ run unordered/move_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_move ]
[ run unordered/assign_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_assign ]
;
test-suite unordered-exception
:
[ run exception/constructor_exception_tests.cpp framework ]
[ run exception/copy_exception_tests.cpp framework ]
[ run exception/assign_exception_tests.cpp framework ]
[ run exception/insert_exception_tests.cpp framework ]
[ run exception/erase_exception_tests.cpp framework ]
[ run exception/rehash_exception_tests.cpp framework ]
[ run exception/swap_exception_tests.cpp framework : : :
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
;
-29
View File
@@ -1,29 +0,0 @@
# Copyright 2006-2008 Daniel James.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import testing ;
#alias framework : /boost/test//boost_unit_test_framework ;
alias framework : ;
project unordered-test/exception-tests
: requirements
<warnings>all
<toolset>intel:<warnings>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
;
test-suite unordered-exception
:
[ run constructor_exception_tests.cpp framework ]
[ run copy_exception_tests.cpp framework ]
[ run assign_exception_tests.cpp framework ]
[ run insert_exception_tests.cpp framework ]
[ run erase_exception_tests.cpp framework ]
[ run rehash_exception_tests.cpp framework ]
[ run swap_exception_tests.cpp framework : : :
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
;
+54 -24
View File
@@ -38,21 +38,18 @@ struct self_assign_test2 : self_assign_base<T>
template <class T>
struct assign_base : public test::exception_base
{
const test::random_values<T> x_values, y_values;
test::random_values<T> x_values, y_values;
T x,y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2,
float mlf1 = 1.0, float mlf2 = 1.0) :
x_values(count1),
y_values(count2),
x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1),
allocator_type(tag1)),
y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2),
allocator_type(tag2))
assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) :
x_values(),
y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
@@ -66,47 +63,80 @@ struct assign_base : public test::exception_base
test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it.
T& y = const_cast<T&>(x1);
// internal structure is hidden, this exposes it, at the cost of
// messing up the data.
if (x_values.size()) {
y.emplace(*x_values.begin());
test::check_equivalent_keys(y);
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
}
}
};
template <class T>
struct assign_test1 : assign_base<T>
struct assign_values : assign_base<T>
{
assign_test1() : assign_base<T>(0, 0, 0, 0) {}
assign_values(unsigned int count1, unsigned int count2,
int tag1, int tag2, 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.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
template <class T>
struct assign_test2 : assign_base<T>
struct assign_test1 : assign_values<T>
{
assign_test2() : assign_base<T>(60, 0, 0, 0) {}
assign_test1() : assign_values<T>(0, 0, 0, 0) {}
};
template <class T>
struct assign_test3 : assign_base<T>
struct assign_test2 : assign_values<T>
{
assign_test3() : assign_base<T>(0, 60, 0, 0) {}
assign_test2() : assign_values<T>(60, 0, 0, 0) {}
};
template <class T>
struct assign_test4 : assign_base<T>
struct assign_test3 : assign_values<T>
{
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
assign_test3() : assign_values<T>(0, 60, 0, 0) {}
};
template <class T>
struct assign_test5 : assign_base<T>
struct assign_test4 : assign_values<T>
{
assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
assign_test4() : assign_values<T>(10, 10, 1, 2) {}
};
template <class T>
struct assign_test5 : assign_values<T>
{
assign_test5() : assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
};
template <class T>
struct equivalent_test1 : assign_base<T>
{
equivalent_test1() :
assign_base<T>(0, 0)
{
test::random_values<T> x_values2(10);
this->x_values.insert(x_values2.begin(), x_values2.end());
this->x_values.insert(x_values2.begin(), x_values2.end());
test::random_values<T> y_values2(10);
this->y_values.insert(y_values2.begin(), y_values2.end());
this->y_values.insert(y_values2.begin(), y_values2.end());
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
EXCEPTION_TESTS(
(self_assign_test1)(self_assign_test2)
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5)
(equivalent_test1),
CONTAINER_SEQ)
RUN_TESTS()
+2 -2
View File
@@ -18,8 +18,8 @@ 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)
rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
: values(count), n(n_)
{}
typedef T data_type;
+2 -2
View File
@@ -66,8 +66,8 @@ struct swap_base : public test::exception_base
{}
struct data_type {
data_type(T const& x, T const& y)
: x(x), y(y) {}
data_type(T const& x_, T const& y_)
: x(x_), y(y_) {}
T x, y;
};
+3 -3
View File
@@ -7,8 +7,8 @@
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <iterator>
namespace test
{
@@ -28,7 +28,7 @@ namespace test
template <class Iterator>
struct input_iterator_adaptor
: public boost::iterator<
: public std::iterator<
std::input_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
std::ptrdiff_t,
@@ -72,7 +72,7 @@ namespace test
template <class Iterator>
struct copy_iterator_adaptor
: public boost::iterator<
: public std::iterator<
BOOST_DEDUCED_TYPENAME boost::iterator_category<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type,
+3 -3
View File
@@ -11,8 +11,8 @@
#if !defined(UNORDERED_TEST_LIST_HEADER)
#define UNORDERED_TEST_LIST_HEADER
#include <boost/iterator.hpp>
#include <boost/limits.hpp>
#include <iterator>
#include <functional>
namespace test
@@ -83,7 +83,7 @@ namespace test
template <typename T>
class list_iterator
: public boost::iterator<
: public std::iterator<
std::forward_iterator_tag, T,
int, T*, T&>
{
@@ -109,7 +109,7 @@ namespace test
template <typename T>
class list_const_iterator
: public boost::iterator<
: public std::iterator<
std::forward_iterator_tag, T,
int, T const*, T const&>
{
+9 -1
View File
@@ -103,8 +103,16 @@ namespace test
struct random_values
: public test::list<BOOST_DEDUCED_TYPENAME X::value_type>
{
random_values(int count, test::random_generator const& generator =
random_values() {}
explicit random_values(int count, test::random_generator const& generator =
test::default_generator)
{
fill(count, generator);
}
void fill(int count, test::random_generator const& generator =
test::default_generator)
{
test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
+1 -1
View File
@@ -148,7 +148,7 @@ namespace test
return ptr;
}
pointer allocate(size_type n, void const* u)
pointer allocate(size_type n, void const*)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
+2 -2
View File
@@ -314,7 +314,7 @@ namespace exception
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
pointer allocate(size_type n, void const* u)
pointer allocate(size_type n, void const*)
{
T* ptr = 0;
UNORDERED_SCOPE(allocator::allocate(size_type, const_pointer)) {
@@ -494,7 +494,7 @@ namespace exception
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
pointer allocate(size_type n, void const* u)
pointer allocate(size_type n, void const*)
{
T* ptr = 0;
UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer)) {
+49 -20
View File
@@ -19,6 +19,12 @@
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
#else
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
#endif
namespace test
{
namespace minimal
@@ -29,7 +35,9 @@ namespace minimal
class default_assignable;
class assignable;
struct ampersand_operator_used {};
struct ampersand_operator_used {
ampersand_operator_used() { BOOST_TEST(false); }
};
template <class T> class hash;
template <class T> class equal_to;
@@ -48,6 +56,7 @@ namespace minimal
public:
destructible(constructor_param const&) {}
~destructible() {}
void dummy_member() const {}
private:
destructible(destructible const&);
destructible& operator=(destructible const&);
@@ -59,6 +68,7 @@ namespace minimal
copy_constructible(constructor_param const&) {}
copy_constructible(copy_constructible const&) {}
~copy_constructible() {}
void dummy_member() const {}
private:
copy_constructible& operator=(copy_constructible const&);
copy_constructible() {}
@@ -78,11 +88,15 @@ namespace minimal
{
}
void dummy_member() const {}
private:
copy_constructible_equality_comparable& operator=(
copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable() {}
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
bool operator==(
@@ -121,9 +135,12 @@ namespace minimal
{
}
private:
void dummy_member() const {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
class assignable
@@ -133,11 +150,13 @@ namespace minimal
assignable(assignable const&) {}
assignable& operator=(assignable const&) { return *this; }
~assignable() {}
void dummy_member() const {}
private:
assignable() {}
// TODO: This messes up a concept check in the tests.
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
struct movable_init {};
@@ -153,6 +172,7 @@ namespace minimal
movable1(BOOST_RV_REF(movable1)) {}
movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
~movable1() {}
void dummy_member() const {}
};
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -164,6 +184,7 @@ namespace minimal
movable2(movable2&&) {}
~movable2() {}
movable2& operator=(movable2&&) { return *this; }
void dummy_member() const {}
private:
movable2() {}
movable2(movable2 const&);
@@ -184,8 +205,10 @@ namespace minimal
~hash() {}
std::size_t operator()(T const&) const { return 0; }
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -199,8 +222,10 @@ namespace minimal
~equal_to() {}
bool operator()(T const&, T const&) const { return true; }
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T> class ptr;
@@ -288,9 +313,10 @@ namespace minimal
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -325,9 +351,10 @@ namespace minimal
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -359,7 +386,7 @@ namespace minimal
}
template <class Y>
pointer allocate(size_type n, const_ptr<Y> u)
pointer allocate(size_type n, const_ptr<Y>)
{
return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
@@ -387,8 +414,10 @@ namespace minimal
#else
private: allocator& operator=(allocator const&);
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -433,7 +462,7 @@ namespace minimal
}
template <class Y>
T* allocate(std::size_t n, const_ptr<Y> u) {
T* allocate(std::size_t n, const_ptr<Y>) {
return static_cast<T*>(::operator new(n * sizeof(T)));
}
+2 -2
View File
@@ -347,7 +347,7 @@ namespace test
return ptr;
}
T* allocate(std::size_t n, void const* u)
T* allocate(std::size_t n, void const*)
{
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
@@ -573,7 +573,7 @@ namespace test
return p;
}
pointer allocate(size_type n, void const* u)
pointer allocate(size_type n, void const*)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
-63
View File
@@ -1,63 +0,0 @@
# Copyright 2006-2008 Daniel James.
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import testing ;
project unordered-test/unordered
: requirements
<warnings>all
<toolset>intel:<warnings>on
# Would be nice to define -Wundef, but I'm getting warnings from
# Boost.Preprocessor on trunk.
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
;
test-suite unordered
:
[ run fwd_set_test.cpp ]
[ run fwd_map_test.cpp ]
[ run allocator_traits.cpp ]
[ run minimal_allocator.cpp ]
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run noexcept_tests.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
[ run incomplete_test.cpp ]
[ run simple_tests.cpp ]
[ run equivalent_keys_tests.cpp ]
[ run constructor_tests.cpp ]
[ run copy_tests.cpp ]
[ run move_tests.cpp ]
[ run assign_tests.cpp ]
[ run insert_tests.cpp ]
[ run insert_stable_tests.cpp ]
[ run unnecessary_copy_tests.cpp ]
[ run erase_tests.cpp ]
[ run erase_equiv_tests.cpp ]
[ run find_tests.cpp ]
[ run at_tests.cpp ]
[ run bucket_tests.cpp ]
[ run load_factor_tests.cpp ]
[ run rehash_tests.cpp ]
[ run equality_tests.cpp ]
[ run swap_tests.cpp ]
[ run compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_set ]
[ run compile_map.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_compile_map ]
[ run copy_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_copy ]
[ run move_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_move ]
[ run assign_tests.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
: bmove_assign ]
;
+4 -4
View File
@@ -22,9 +22,9 @@
T const* address(T const& r) { return &r; } \
T* allocate(std::size_t n) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
T* allocate(std::size_t n, void const* u) \
T* allocate(std::size_t n, void const*) \
{ return static_cast<T*>(::operator new(n * sizeof(T))); } \
void deallocate(T* p, std::size_t n) { ::operator delete((void*) p); } \
void deallocate(T* p, std::size_t) { ::operator delete((void*) p); } \
void construct(T* p, T const& t) { new(p) T(t); } \
void destroy(T* p) { p->~T(); } \
std::size_t max_size() const \
@@ -44,9 +44,9 @@
const_pointer address(T const& r) { return &r; } \
pointer allocate(std::size_t n) \
{ return pointer(::operator new(n * sizeof(T))); } \
pointer allocate(std::size_t n, void const* u) \
pointer allocate(std::size_t n, void const*) \
{ return pointer(::operator new(n * sizeof(T))); } \
void deallocate(pointer p, std::size_t n) \
void deallocate(pointer p, std::size_t) \
{ ::operator delete((void*) p); } \
void construct(T* p, T const& t) { new(p) T(t); } \
void destroy(T* p) { p->~T(); } \
-1
View File
@@ -16,7 +16,6 @@ UNORDERED_AUTO_TEST(at_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x;
typedef boost::unordered_map<std::string, int>::iterator iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
+2
View File
@@ -202,6 +202,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
boost::unordered_map<
test::minimal::assignable,
@@ -226,6 +227,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
}
RUN_TESTS()
+2
View File
@@ -183,6 +183,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
std::cout<<"Test unordered_multiset.\n";
@@ -195,6 +196,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
}
UNORDERED_AUTO_TEST(movable1_tests)
+67
View File
@@ -148,6 +148,7 @@ void unordered_destructible_test(X&)
X* ptr = new X();
X& a1 = *ptr;
(&a1)->~X();
::operator delete((void*)(&a1));
X a,b;
X const a_const;
@@ -180,6 +181,28 @@ void unordered_set_test(X&, Key const&)
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
}
template <class X, class Key, class T>
@@ -191,6 +214,30 @@ void unordered_map_test(X& r, Key const& k, T const& v)
BOOST_STATIC_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
// Calling functions
r.insert(std::pair<Key const, T>(k, v));
Key k_lvalue(k);
@@ -508,3 +555,23 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
sink(a8);
sink(a10);
}
template <class X, class T>
void unordered_set_member_test(X& x, T& t)
{
X x1(x);
x1.insert(t);
x1.begin()->dummy_member();
x1.cbegin()->dummy_member();
}
template <class X, class T>
void unordered_map_member_test(X& x, T& t)
{
X x1(x);
x1.insert(t);
x1.begin()->first.dummy_member();
x1.cbegin()->first.dummy_member();
x1.begin()->second.dummy_member();
x1.cbegin()->second.dummy_member();
}
+8
View File
@@ -95,12 +95,16 @@ void erase_tests1(Container*, test::random_generator generator)
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
BOOST_TEST(next == x.erase(pos));
--size;
if(size > 0)
BOOST_TEST(index == 0 ? next == x.begin() :
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
std::cerr << count << " => " << x.count(key) << std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
@@ -180,12 +184,16 @@ void erase_tests1(Container*, test::random_generator generator)
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
x.quick_erase(pos);
--size;
if(size > 0)
BOOST_TEST(index == 0 ? next == x.begin() :
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
std::cerr << count << " => " << x.count(key) << std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) test::check_equivalent_keys(x);
}
+2
View File
@@ -40,8 +40,10 @@ void find_tests1(X*, test::random_generator generator)
iterator pos = x.find(key);
BOOST_DEDUCED_TYPENAME X::const_iterator
const_pos = x_const.find(key);
BOOST_TEST(pos != x.end());
BOOST_TEST(pos != x.end() &&
x.key_eq()(key, test::get_key<X>(*pos)));
BOOST_TEST(const_pos != x_const.end());
BOOST_TEST(const_pos != x_const.end() &&
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
+4
View File
@@ -598,7 +598,11 @@ UNORDERED_AUTO_TEST(insert_initializer_list_set)
boost::unordered_set<initialize_from_two_ints> set2;
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))
set2.insert({{1, 2}});
#else
set2.insert({1, 2});
#endif
BOOST_TEST(set2.size() == 1);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({2,1}) == set2.end());
+1 -1
View File
@@ -18,7 +18,7 @@ struct SimpleAllocator
{
}
template <class T> SimpleAllocator(const SimpleAllocator<T>& other)
template <class T> SimpleAllocator(const SimpleAllocator<T>&)
{
}