Compare commits

...

239 Commits

Author SHA1 Message Date
Glen Fernandes 0960f885d5 Merge branch 'develop' 2020-11-01 08:21:59 -05:00
Peter Dimov 33b28a514e Update .appveyor.yml 2020-08-24 12:41:56 +03:00
Peter Dimov 2497d663b7 Merge pull request #16 from eldiener/develop
Changes for Embarcadero C++ clang-based compilers, targeting Boost 1.74. Change __BORLANDC__ to BOOST_BORLANDC and __CODEGEARC__ to BOOST_CODE…
2020-08-24 12:39:36 +03:00
Edward Diener 887f1dc07c Change __BORLANDC__ to BOOST_BORLANDC and __CODEGEARC__ to BOOST_CODEGEARC, which are3defined in Boost config for the Embarcadero non-clang-based compilers. 2020-03-31 22:47:48 -04:00
Daniel James 9abce00f24 Merge branch 'develop' 2018-04-16 07:05:46 +01:00
Daniel James f3649e4ae0 Use boost 1.67.0 in tests 2018-04-15 22:39:33 +01:00
Daniel James 6cf0342322 Stop using -Werror
So that it doesn't fail for warnings in other libraries.
2018-04-15 22:39:33 +01:00
Daniel James 3252ad1f4b Move download-boost-snapshot.py into ci directory
Because __boost_check_library__ is complaining about it.
2018-03-18 15:41:24 +00:00
Daniel James 741a10f5a8 Merge branch 'develop' 2018-03-06 22:27:23 +00:00
Daniel James c39dd284d2 Boost 1.67.0 changelog 2018-03-05 14:20:14 +00:00
Daniel James 4e5c97f3a3 Merge branch 'develop'
- Various CI improvements, including appveyor support
- Stop using boost::next in tests, because of warnings
- Use std::iterator_traits, to drop dependency on iterator
- Use std::piecewise_construct from dinukumware/Visual C++
- Template deduction guides, just copied from the standard,
  they don't work that well. I think some other implementations
  enhance them
- Some internal changes
- Stop inheriting from std::iterator, deprecated in C++17 (#7)
- Implement allocator_traits::is_always_equal
- Rewrite node handles using a simple class based on std::optional,
  so that it's closer to the standard
- noexcept support for swap, operator=
- Fix some compiler warnings
- Fix some of the tests on Visual C++ 7.1
- Add element_type to iterators, so that pointer_traits will work
- Use boost::to_address internally, instead of own custom implementation
- Stop using BOOST_DEDUCED_TYPENAME - it's for very old compilers that are
  no longer supported, and makes the code look ugly
2018-02-25 14:06:04 +00:00
Daniel James e10fc0f93b Fix typo 2018-02-25 14:03:11 +00:00
Daniel James 8207ebe381 Use bash to run bootstrap.sh
When using a zipfile it isn't marked as executable.
2018-02-09 09:00:45 +00:00
Daniel James 6491f6c10a Python script to download the latest snapshot for CI testing 2018-02-02 23:37:36 +00:00
Daniel James cfd4bacc2c Stop using BOOST_DEDUCED_TYPENAME
We no longer support any of the compilers that require it. I'd be very
surprised if anything was working on them.
2018-01-27 09:39:59 +00:00
Daniel James 09be9bae04 Use boost::is_nothrow_swappable, now that it's available everywhere 2018-01-27 09:38:19 +00:00
Daniel James c01a8c4629 Oops, it's boost::to_address, no boost::to_pointer 2018-01-26 20:25:09 +00:00
Daniel James cdb0229cf2 Use snapshot to get latest pointer_traits 2018-01-26 20:01:29 +00:00
Daniel James ddf302fcc2 Use boost::to_pointer instead of pointer<..>::get
To get C++20 style recursive calls to `operator->`.
2018-01-26 18:59:16 +00:00
Daniel James ca9e9584ba Test on appveyor 2018-01-26 18:03:56 +00:00
Daniel James 0d34053870 Use boost::to_address in node_handle_tests 2018-01-26 17:47:47 +00:00
Daniel James 66533ace80 Add element_type to nodes, so that pointer_traits will work
Might be better to change the template signature of iterators, but that would
be a disruptive change to make at the moment.
2018-01-26 17:43:06 +00:00
Daniel James ea599a66b7 Disable 'conditional expression is constant' on older Visual C++ 2018-01-23 15:40:58 +00:00
Daniel James 1cc3f680e8 Fix a couple more explicit default constructors for Visual C++ 7.1 2018-01-20 11:49:07 +00:00
Daniel James f7665a2743 Another attempt to fix insert_exception_tests on Visual C++ 7.1
Try extracting the nested template structs.
2018-01-20 08:57:56 +00:00
Daniel James dc9faddf22 Try to fix constructor_tests on Visual C++ 7.1
I'm really not sure why it fails to compile, the error message isn't very
helpful.  I assume it might be because allocator1 has an explicit default
constructor, so I tried making it implicit.
2018-01-17 10:40:58 +00:00
Daniel James e64c5b34df Try to fix insert_exception_tests on Visual C++ 7.1
It doesn't seem to like the nested template structs. If this doesn't work, I'll
try moving them into the top level.
2018-01-17 10:24:07 +00:00
Daniel James 57492c1a94 Make allocator comparison const in allocator_traits test 2018-01-13 20:31:45 +00:00
Daniel James df8fbca007 Double brackets for BOOST_STATIC_ASSERT 2018-01-13 20:31:45 +00:00
Daniel James 72fb9c7c96 Suppress warnings in noexcept_tests 2018-01-13 20:31:45 +00:00
Daniel James ce0f16f328 Missing copyright messages 2018-01-10 15:15:09 +00:00
Daniel James a477d70f32 Add explicit failure for noexcept_tests on gcc + fix description for Visual C++ 7.1 2018-01-10 11:46:13 +00:00
Daniel James f3476de893 Some explicit casts to avoid warnings on old GCC 2018-01-10 11:35:42 +00:00
Daniel James dea525b2b7 Suppress msvc waring "conditional expression is constant" 2018-01-10 11:35:22 +00:00
Daniel James d55c9565ab No template arguments in BOOST_MOVABLE_BUT_NOT_COPYABLE
Was causing errors on Visual C++ 7.1.
2018-01-10 09:58:08 +00:00
Daniel James 00a4185cf1 Reformat 2018-01-08 10:58:09 +00:00
Daniel James ea28a3f98e Fix conversion to bool warning 2018-01-08 10:57:28 +00:00
Daniel James c8facc99a7 Run concurrent test processes in travis 2018-01-06 14:25:38 +00:00
Daniel James d7ec41f4c6 Add final use of CXXSTD in travis 2018-01-06 14:14:59 +00:00
Daniel James 9f2063846b Build b2 from the source snapshot 2018-01-06 13:38:56 +00:00
Daniel James c05c541216 Use boost build's new cxxstd feature 2018-01-06 13:37:04 +00:00
Daniel James 34e54b35e8 Manually handle assigning hash/equality functions 2018-01-06 12:53:37 +00:00
Daniel James f12009fc61 operator= noexcept support 2018-01-05 17:54:44 +00:00
Daniel James 5854090dc7 Swap noexcept support
Not properly supported as we don't have is_nothrow_swappable yet.
2018-01-05 17:48:13 +00:00
Daniel James 7e28fdd45a Make the current function_pair public 2018-01-05 17:10:13 +00:00
Daniel James daeaf5e98b Flexible exception testing hash/equal_to 2018-01-05 17:10:13 +00:00
Daniel James 4bffd7a85d Avoid some warnings 2018-01-04 18:29:31 +00:00
Daniel James 7615fabc80 Rewrite node handles using a lightweight limited optional
Will try to use std::optional when available. Also using
allocator_traits::is_always_equal support.
2018-01-03 23:15:55 +00:00
Daniel James be0acc575f Implement allocator_traits::is_always_equal 2018-01-03 20:55:40 +00:00
Daniel James 9d558b010d Reformat 2017-12-28 11:44:57 +00:00
Daniel James 32773fb023 Merge pull request #7 from DanielaE/fix/no-iterator-inheritance
Inheriting std::iterator is deprecated in c++17.
2017-12-28 11:31:11 +00:00
Daniela Engert 64441d2b64 Inheriting std::iterator is deprecated in c++17.
Therefore get rid of all of that and replace inheritance by lifting std::iterator's members into the derived class.

Signed-off-by: Daniela Engert <dani@ngrt.de>
2017-12-28 12:01:41 +01:00
Daniel James 07758b7af8 Catch exceptions by reference 2017-12-22 17:02:13 +00:00
Daniel James 92ce66be64 Rename 'bucket' variable to avoid shadow warning 2017-12-22 16:54:05 +00:00
Daniel James 15befe998e Rename table::get_bucket to get_bucket_pointer
All the other '*_bucket' methods return a bucket index.
2017-12-22 16:44:43 +00:00
Daniel James b50e0d610f Initial implementation of template deduction guides 2017-12-19 12:56:51 +00:00
Daniel James f99dee1917 Use predef for detecting piecewise construction
And detect it for recent dinkumware.
2017-12-19 12:11:36 +00:00
Daniel James 6327d174d2 Test C++17 mode in travis 2017-12-19 12:11:35 +00:00
Daniel James c2b9b22f67 Use 1.66.0 in tests 2017-12-19 12:10:53 +00:00
Daniel James 311e126ac4 Remove dependency on iterator 2017-12-03 18:58:52 +00:00
Daniel James c037169e1a Update paths for headers moved from detail 2017-12-03 14:24:47 +00:00
Daniel James 9bb861accc Use std::advance in test::next, and use it instead of boost::next
Mainly to avoid warnings from boost::next
2017-12-01 08:35:38 +00:00
Daniel James ecd5b239a4 Use appropriate snapshot when testing on travis 2017-12-01 07:57:29 +00:00
Daniel James a600ef6cbb Merge branch 'develop' 2017-11-11 18:38:48 +00:00
Daniel James b90da4a802 1.66.0 release notes 2017-11-10 15:12:37 +00:00
Daniel James c50ba694a5 Use quickbook 1.7 2017-11-10 15:12:09 +00:00
Daniel James 8f7b7ca7b3 Update clang format comment for 4.0.0 2017-10-29 16:52:46 +00:00
Daniel James adfc7f4d5d Generate ref.xml 2017-10-28 22:58:21 +01:00
Daniel James 9e18dc1401 Oops, fix properly 2017-10-28 17:36:25 +01:00
Daniel James cf76763ab7 Fix node handle description 2017-10-28 17:34:28 +01:00
Daniel James fb7ef4cf63 Build documentation using consistent ids 2017-10-25 01:16:59 +01:00
Daniel James 04a0909105 Merge branch 'develop' 2017-10-22 16:12:47 +01:00
Daniel James 613f154d47 Improved test formatting 2017-10-09 12:34:47 +01:00
Daniel James 978944fab2 Use same code for move constructing all containers
Copies the data layout from the source, so it doesn't need to hash anything.
2017-10-05 10:56:02 +01:00
Daniel James 705e69aefd Always call set_first_in_group
Probably don't need to, as we're using 0 for the first element in a group, but
it's quick so might as well.
2017-10-05 10:54:23 +01:00
Daniel James e58081f6dc Drop some TODOs that are okay 2017-10-05 10:54:22 +01:00
Daniel James 4ac8a45a34 The max_load issue was fixed in the standard ages ago 2017-10-05 10:54:22 +01:00
Daniel James 6b5b968b97 Format with clang-format 4.0 2017-10-05 10:54:22 +01:00
Daniel James 2ab82ad653 Merge branch 'develop' 2017-10-02 18:00:09 +01:00
Daniel James 86df284ad4 Add explicit-failures-markup.xml 2017-10-02 17:34:51 +01:00
Daniel James 3521c87e17 Merge branch 'develop'
Documentation fixes.
2017-09-19 11:04:08 +01:00
Daniel James 32533f7325 Merge branch 'develop'
Formatting changes
2017-09-19 11:03:26 +01:00
Chris Needham 0e19bdf50a Documentation fixes 2017-09-07 22:56:54 +01:00
Daniel James f72b0353d4 Shuffle code around for readability
The new indentation made some of the code difficult to read, especially
where macros were concerned, so move things around and add more explicit
namespace declarations.
2017-06-11 20:55:59 +01:00
Daniel James 0676b4f4ca Change clang format indentation + .editorconfig file 2017-06-11 20:55:59 +01:00
Daniel James 929982357a Merge branch 'develop' 2017-06-11 20:54:52 +01:00
Daniel James 5190a5d7f8 Stop dereferencing pointers to uninitialized memory
It's undefined behaviour. Still happens for piecewise construction
emultation for std::pair, I don't think there's anyway to avoid it.
I had considered using offsetof to get a pointer to a member, but that's
also undefined behaviour when a pair member doesn't have standard
layout. Piecewise construction emulation has other problems anyway.

So, this mostly fixes PR #5.

I also stopped using addressof in self-asssignment checks as operator&
is fine.
2017-06-04 08:47:02 +01:00
Daniel James 7775aa83df Decrease the limit for SunOS workaround
We have tests for 12.5 (5,20,0), and 12.5_next (5,21,0), I think both
are good enough to not require workarounds.
2017-05-25 08:53:34 +01:00
Daniel James fc1604f2c8 Don't use allocator_traits::construct on GCC 4.6
Piecewise construction doesn't work uncopyable types.
2017-05-19 17:24:44 +01:00
Daniel James 5b97fbc292 Make insert from node_handle move only on old GCC 2017-05-19 09:42:56 +01:00
Daniel James 4f5a2dabe9 Try to fix std::tuple on old Sun compilers
In order to use the workaround for both `boost::tuple` and `std::tuple`
the function would need to detect which was being used, in order to
decide whether to use `boost::tuples::length` or `std::tuple_size`.
Probably not difficult, but I don't have any way to test an
implementation.

So instead Just assume that if `std::tuple` is available it will work
without any workaround. Presumably once the compiler was able to support
`std::tuple` it will also support the necessary overloads.

I've left the version check as 5.21 so that failures will still show up
in the tests, but I'm sure it can be 5.20 and probably earlier.  Will
change before release.
2017-05-19 09:03:08 +01:00
Daniel James e0227618bb Move a few things around to match the order in the standard 2017-05-17 16:47:57 +01:00
Daniel James ee9a5a2c77 Add a configuration macro for Sun C++ workarounds 2017-05-16 19:01:50 +01:00
Daniel James 6fffc738f7 Require std::tuple for full C++11 construction 2017-05-16 18:15:56 +01:00
Daniel James dc611fc828 Run fewer test in merge_exception_tests
It's timing out on some platforms because it's too slow. This reduces
the tag combinations for 9 to 3, which should reduce the execution time
by a third. Also slightly reduces the count combinations, but that won't
make much of a difference really - the slowest tests are still there
(when the right hand side is large).
2017-05-14 02:59:22 +01:00
Daniel James 12ee29579d Don't use full construction on Sun C++ w. libstdc++
There's an exception safety issue. Which is a pity as other than that it
seems fine. I'd assumed that support would be pretty good on all C++11
compilers, so I made it an 'all or nothing' feature, partly because
there are issues with pre-C++11 allocators, but this suggests partial
support might be desirable. Not sure I'll be able to (or want to) put
the time in though.
2017-05-12 21:58:52 +01:00
Daniel James a897843f6c Try to work around an MSVC bug
Although, perhaps I shouldn't be generating over 1000 runs for a test.
2017-05-11 00:36:31 +01:00
Daniel James 80de85f217 Move test state + functions into single class 2017-05-10 19:02:47 +01:00
Daniel James 242e91a9fd "Sub-test" reporting mechanism 2017-05-10 19:02:47 +01:00
Daniel James ca80237191 Create fewer classes in merge_exception_tests
Will need better error reporting capabilities. Makes RUN_TESTS_QUIET
redundant?
2017-05-10 19:02:47 +01:00
Daniel James b95ef6de04 Generate less output in merge_exception_tests 2017-05-10 19:02:47 +01:00
Daniel James 76e7322262 Use streams from lightweight test 2017-05-10 19:02:47 +01:00
Daniel James 3c42138e45 Fix testing piecewise_construct and tuple
For when std::piecewise_construct is available, but std::tuple isn't. In
order to test better, just repeat the tests with the four possible
combinations.
2017-05-08 18:42:53 +01:00
Daniel James 1b0b38a519 try_emplace, insert_or_assign exception tests 2017-05-07 18:47:59 +01:00
Daniel James 9119a42b7d Factor insert_exception_tests for better code reuse 2017-05-07 18:47:24 +01:00
Daniel James 8af4b37d14 Rewrite insert exception tests
Not going to do this for all the tests. It's more effort than I
expected.
2017-05-07 17:54:34 +01:00
Daniel James 31c5b5bfa1 Merge exception tests 2017-05-07 17:54:34 +01:00
Daniel James b6c6bfbe7f Statically handle 'is_unique' in assignments 2017-05-06 04:58:57 +01:00
Daniel James 6e074d7165 Get rid of delete_nodes 2017-05-06 04:58:57 +01:00
Daniel James 0489069419 Use 'limited_range' to catch error in exception tests
This would have caught the error fixed in 3fe259a79e.
2017-05-06 04:47:59 +01:00
Daniel James 597eb5a3fd Repeat the assign/insert exception tests a few times 2017-05-06 04:47:59 +01:00
Daniel James 3fe259a79e Fix creating exception::less from exception::equal_to 2017-05-05 12:58:26 +01:00
Daniel James 6ef17a0f0e Remember to disable exceptions before checking final value 2017-05-05 00:46:07 +01:00
Daniel James 47a8c3fc67 Fix exception handling in rehash_impl
And improve tests so they will catch the error, and other similar errors.
2017-05-04 19:30:18 +01:00
Daniel James d49d0e90a8 Delete nodes directly instead of through previous node 2017-05-04 00:14:08 +01:00
Daniel James 77bd45b1fa Make second parameter of delete_nodes a node_pointer 2017-05-04 00:14:05 +01:00
Daniel James 622dff50df Fix some code that could be using next_node 2017-05-03 23:36:09 +01:00
Daniel James 41f6a051ef Some more configuration comments 2017-05-03 04:21:53 +01:00
Daniel James d05619095c Workaround problems with forward_as_tuple in older versions of clang 2017-05-03 04:21:52 +01:00
Daniel James 2f8492d720 Fix libc++ configuration 2017-05-03 04:21:52 +01:00
Daniel James 7911f491f6 Try using own allocator_traits with Sun compiler
The good news is that the old Sun workarounds aren't needed any more.
Unfortunately, there are a lot of exception test errors for
unordered_map and unordered_multimap when using libstdc++, which
probably means that std::pair isn't exception safe, which is a bit odd.
But first try using our allocator_traits implementation instead of the
standard one to see if that makes a difference. If it doesn't then I'll
probably just disable C++11 construction on this compiler, which should
fix the problem but will make allocators less useful.
2017-05-03 04:21:52 +01:00
Daniel James d84a57441b Use the unordered container for the fake merge in merge test
The merge tests into containers with unique keys are failing on some
platforms. My guess is that because of differences between ordering of
nodes with equivalent keys that different nodes are being 'merged' in
the unordered containers and the tracker containers. So when creating
the fake merge, use the unordered container as a reference. This is a
little less pure, but should be a good enough test.
2017-05-01 22:16:13 +01:00
Daniel James b8c754d230 Set the high bit in bucket_info_ to false for first node in group
And true for the reset, so that in containers with unique keys
bucket_info_ is always just the bucket index.
2017-05-01 21:03:11 +01:00
Daniel James 338a94e577 Better rvalue emulation support in extractors
Means that inserting rvalues into unordered_set/unordered_map won't
create a node if no insert is required.
2017-05-01 21:03:11 +01:00
Daniel James 2e14c340a8 Reformat 2017-05-01 21:03:11 +01:00
Daniel James 35522d3ee0 Fix merging between containers with different hash/equality
This reverts commit 20b0c0a6d8.
2017-04-30 14:29:05 +01:00
Daniel James 8c139940e7 More merge tests between compatible containers 2017-04-30 14:29:05 +01:00
Daniel James 7b5f73f6c2 Disable all sunpro workarounds on latest version
I have no idea if they're still working. I wasn't able to run the latest
solaris in a virtual machine on my computer, so this is the only way to
test.
2017-04-30 10:44:54 +01:00
Daniel James e7a3487df4 Remove policy template parameter from local iterators 2017-04-30 10:44:54 +01:00
Daniel James c243895fc0 Remove odd check that should never be true
I think it was left over from the old grouped node implementation.
2017-04-30 10:44:54 +01:00
Daniel James 451d0f2fc5 Constructing nodes is nothrow, so no need to track 2017-04-30 10:43:06 +01:00
Daniel James c75b332240 Cleaner create_buckets implementation 2017-04-30 10:43:06 +01:00
Daniel James 899248acbf Avoid shadow warning on older versions off GCC 2017-04-29 09:31:17 +01:00
Daniel James cae6b121b2 Improve test coverage a little 2017-04-28 21:26:21 +01:00
Daniel James 5f6ee3da9c Use coveralls 2017-04-28 09:53:50 +01:00
Daniel James bfcdd51b4a Fix try_emplace overload 2017-04-28 09:53:50 +01:00
Daniel James 10b736d407 Remove BOOST_UNORDERED_CALL_CONSTRUCT0 2017-04-28 09:53:50 +01:00
Daniel James 0b61e6defb Stop using allocators to construct/destroy internal types
The standard doesn't allow it. I should have known that.
2017-04-27 19:02:10 +01:00
Daniel James 28f529100d Merge branch 'feature/simpler-data-structure' into develop
C++17 requires that unordered_map has the same type of node as
unordered_multimap, and that unordered_set has the same type of node as
unordered_multiset. This didn't seem particularly useful to me and
contradicts the old implementation which had different nodes, I put a
lot of effort into trying to abstract out the difference and make it
selectable using a macro, so that the old implementation would still by
available for anyone who doesn't care about strict compatibility.

But I think that was a mistake, it was making things too complicated and
for too little gain. The default would still be inefficient containers
for equivalent keys, and using the macro could lead to problems down the
line.

So I've switched to using a much simpler implementation which just marks
the first node in a group of equivalent nodes. This isn't as fast when
there are a lot of elements with equivalent keys - it can't skip to the
end of a group of nodes, but at least it avoids having to do a lot of
potentially expensive comparisons.

It's also a lot closer to the intent of the standard, even if I disagree
with that intent.
2017-04-27 18:22:53 +01:00
Daniel James 6466ce0b51 Make table the same for unique and equivalent keys 2017-04-27 18:22:44 +01:00
Daniel James 03baef8b28 Remove Types::is_unique 2017-04-27 18:22:44 +01:00
Daniel James f1435d53d4 Remove 'init' method from nodes 2017-04-27 18:22:44 +01:00
Daniel James 20b0c0a6d8 Only consider one node from each group in merge_unique 2017-04-27 18:22:44 +01:00
Daniel James a1b1df84a0 Store bucket + whether first in group in node
Instead of the hash value.
2017-04-27 18:22:44 +01:00
Daniel James 408ebd0a0a Add node_bucket function 2017-04-27 18:22:44 +01:00
Daniel James e9c4696544 Get rid of node_algo 2017-04-27 18:22:43 +01:00
Daniel James ea64f2e46e Remove the grouped node stuff 2017-04-27 18:22:43 +01:00
Daniel James 94a3a9baf9 Fix some quickbook markup 2017-04-25 21:14:11 +01:00
Daniel James da27ae4de6 Group together similar overloads of try_emplace 2017-04-25 20:20:11 +01:00
Daniel James ed326e2c87 Expand out more preprocessor repeats 2017-04-25 20:20:11 +01:00
Daniel James bea4c6e29b undef some macros 2017-04-25 20:20:11 +01:00
Daniel James 61df9479e5 Rename unique_node 2017-04-25 20:20:11 +01:00
Daniel James e3ab7b5d2e Remove BOOST_UNORDERED_EMPLACE_ARGSn macros
They're not used anywhere now.
2017-04-25 20:20:11 +01:00
Daniel James 679b73098e Option to use grouped nodes everywhere
Seems to work okay, but I'm not happy with and of the options. So I'm
going to look into doing something else before the next release.
2017-04-25 09:54:28 +01:00
Daniel James cba643fc51 Make setting max_load_ a tad more consistent 2017-04-25 09:54:28 +01:00
Daniel James 1c8edf0298 Remove early exit for empty containers 2017-04-25 09:54:28 +01:00
Daniel James 07b9a7d60e Fix incorrect try_emplace call 2017-04-25 01:39:30 +01:00
Daniel James 9c8980e6a1 Write out epoint that threw an exception after failure 2017-04-25 01:21:44 +01:00
Daniel James 60127d86e0 After 5 failures stop running an exception test 2017-04-25 01:10:53 +01:00
Daniel James 0c3c738614 Better C++ version info 2017-04-25 01:09:07 +01:00
Daniel James c8bacbcb00 Merge branch 'feature/combine-unique-equiv-tables' into develop
Expanding a lot of the call to the implementation methods. While working
on some recent changes, I felt the call chains in error messages were
too long, this reduces that a little. It also should make debugging a
tad easier and I think it makes the methods a little more informative,
as you can see what they're doing without hunting around the
implementation file. Also reduces the number of symbols when compiling,
although I'm not sure if that will make much of a difference.

Does make the code a little long, and duplicated, but I don't think it's
particularly harmful.
2017-04-24 09:46:05 +01:00
Daniel James b070bb5e49 Move everything from table_unique/table_equiv into table 2017-04-24 09:46:05 +01:00
Daniel James e518120104 Rename some copy/assign/move methods
But with a hack so that the static casts will work until there's a
better method.
2017-04-24 09:46:05 +01:00
Daniel James 84f1ef6d2d Move constructor implementation into containers 2017-04-24 09:46:05 +01:00
Daniel James 77bf2b5e33 Rename methods to be different for unique/equiv keys
So that the implementation can be moved into a single class. Still some
other methods to rename. Some methods didn't need to be renamed (e.g.
try_emplace is only used with unique keys), but still renamed for
consistency.
2017-04-24 09:46:05 +01:00
Daniel James 8229aa6b3c Stop throwing exception in allocator copy/assignment
The standard specifies that all of these "shall not exit via an
exception". The containers have been exception safe when these throw,
but the 'noexcept' attribute on 'get_allocator' will terminate if an
exception is thrown in the copy constructor.

The standard doesn't specify a default constructor, so that is allowed
to throw an exception (not just pedantry, this makes sense if an
allocator has shared data that's allocated in the initial constructor).
2017-04-23 11:01:04 +01:00
Daniel James fc08f62d6a Remove a TODO 2017-04-23 10:51:17 +01:00
Daniel James 1254520438 Merge branch 'feature/expand-calls' into develop
Expanding a lot of the call to the implementation methods. While working
on some recent changes, I felt the call chains in error messages were
too long, this reduces that a little. It also should make debugging a
tad easier and I think it makes the methods a little more informative,
as you can see what they're doing without hunting around the
implementation file. Also reduces the number of symbols when compiling,
although I'm not sure if that will make much of a difference.

Does make the code a little long, and duplicated, but I don't think it's
particularly harmful.
2017-04-23 10:46:27 +01:00
Daniel James 7941771d61 Expand calls to at implementation 2017-04-23 10:09:18 +01:00
Daniel James 4f1c6e1ebf Expand calls to init/move_init 2017-04-23 10:09:18 +01:00
Daniel James 13ff1e7fb1 Expand calls to count and equal_range implementation 2017-04-23 10:09:18 +01:00
Daniel James 25b0b66e52 Expand calls to erase implementation
Doesn't work as well as the previous changes.
2017-04-23 10:09:18 +01:00
Daniel James da835e88b8 Expand calls to insert_range 2017-04-23 10:09:18 +01:00
Daniel James b6c229e2bb Expand calls to reserve implementation 2017-04-23 10:09:18 +01:00
Daniel James 19a45e028a Expand calls to generic_find_node 2017-04-23 10:09:18 +01:00
Daniel James 435b7450d4 Expand calls to max_size implementation 2017-04-23 10:09:18 +01:00
Daniel James a41a0f3a06 Expand calls to load_factor implementation 2017-04-23 10:09:18 +01:00
Daniel James 814926ef31 Expand calls to clear implementation 2017-04-23 10:09:18 +01:00
Daniel James f6f5ecdc00 Expand calls to emplace implementation
Also manually call the emplace macro up to 9 arguments, nicer error
messages for little effort.

Does it matter that there's no longer a nice backend for
`please_ignore_this_overload`? I don't think so, I was worried that it
would be confusing if triggered, but I'm not really aware of that ever
happening.
2017-04-23 10:09:18 +01:00
Daniel James 42b6b13943 Use the preprocessor to increment emplace limit
So that there's no need to add one.
2017-04-23 10:04:28 +01:00
Daniel James cfe4c26f99 Explicitly write out boost::tuple template arguments
GCC 4.6 doesn't support using variadic arguments for a fixed length template.
There's a config macro for this, but might as well use the same code
everywhere.
2017-04-23 09:31:18 +01:00
Daniel James 3117611a55 New tuple implementation
Adjusts to use less arguments on Visual C++ 11, which will hopefully fix
it on that compiler. Also changed to be a little less preprocessor
heavy. I'm not sure about the __SUNPRO_CC support, hopefully recent
versions of that compiler will have better support, and can use the
normal implementation. Will check that later.
2017-04-22 18:31:10 +01:00
Daniel James 1e491533fa More consistent std::tuple configuration
Was getting a weird test failure for Visual C++ 11,
BOOST_NO_CXX11_HDR_TUPLE is defined, so the code doesn't support
std::tuple, but BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT was also
true, and so there are functions for constructing using
std::piecewise_construct/std::tuple, which don't work.

So, I'm assuming that if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT is true,
then there must be a std::tuple. I guess it doesn't have full C++11 support,
which is why BOOST_NO_CXX11_HDR_TUPLE is defined, but it appears to be
good enough for us. If not, this will break things.
2017-04-21 20:32:56 +01:00
Daniel James a119caaa1b Stop travis build after first failure 2017-04-20 23:39:44 +01:00
Daniel James 96f8f85eef Use environment variable to set user-config.jam 2017-04-20 23:39:44 +01:00
Daniel James 2add451d63 Use boost 1.64.0 on travis 2017-04-20 23:11:28 +01:00
Daniel James 3effedb728 Merge branch 'feature/standards-checking-and-cleanup' into develop
Rearrange the definitions to be a closer match to the standard, this
should make it easier to check how standards compliant it is. Also, some
minor code clean-ups that I noticed while doing this.
2017-04-20 23:01:09 +01:00
Daniel James b067e65731 Clean table forward declarations 2017-04-20 22:59:00 +01:00
Daniel James f3b179d451 Remove pointless duplication of move constructor 2017-04-20 22:59:00 +01:00
Daniel James de5373413b Missing rvalue overload of at 2017-04-20 22:59:00 +01:00
Daniel James fedf533699 Move index functions into place 2017-04-20 22:59:00 +01:00
Daniel James 9cd673c71d Specify clear as noexcept 2017-04-20 22:59:00 +01:00
Daniel James 85a834cf62 Comment on changes needed for C++17 support 2017-04-20 22:59:00 +01:00
Daniel James 5167c970af Swap order of swap/clear to match standard 2017-04-20 22:59:00 +01:00
Daniel James bf7a65010c Add new erase(iterator) overloads
Not for unordered_set/unordered_multiset as they use the same type for
iterator and const_iterator.
2017-04-20 22:59:00 +01:00
Daniel James 461ac96a2c Reorder insert_or_assign to match standard 2017-04-20 22:59:00 +01:00
Daniel James 5eb10fd0b2 Move extract into place 2017-04-20 22:59:00 +01:00
Daniel James e2e9959389 Split up emplace and emplace_hint code
Busywork I guess, but I think it's more readable this way. The emplace
macros are still unreadable, but I think they're rarely used.

Btw. a bit weird that clang format has removed the indentation on the
'// emplace' comment, not sure why that is.
2017-04-20 22:59:00 +01:00
Daniel James d8969c71fc Move 'try_emplace' into same order as draft standard 2017-04-20 22:59:00 +01:00
Daniel James ab76814aa6 Move 'insert_or_assign' into same order as draft standard 2017-04-20 22:59:00 +01:00
Daniel James 1a18cd2196 Move capacity functions to match order in standard 2017-04-20 22:59:00 +01:00
Daniel James e4a00980f8 Commented out noexcept for move assignment 2017-04-20 22:59:00 +01:00
Daniel James af94e6a40e Reorder the constructors to match the draft standard
In order to make it easier to check against the standard.  This includes
collapsing some of the input iterator overloads into one constructor.
2017-04-20 22:59:00 +01:00
Daniel James ee73a53497 Disable failing tests on gcc 4.6/4.7 c++11 mode
Works fine on later versions of GCC, I suspect it's a bug in their
noexcept support.
2017-04-20 10:11:01 +01:00
Daniel James 6bdf1ba244 Fix a comment 2017-04-19 10:21:13 +01:00
Daniel James d47754acac Include unordered macro values in test output 2017-04-19 10:21:13 +01:00
Daniel James cee94e9fcb Fix unused parameter warning 2017-04-19 09:20:31 +01:00
Daniel James 3ae9930979 Merge branch 'feature/better-construction' into develop 2017-04-18 10:14:53 +01:00
Daniel James 2effcfa195 Intro to compliance section
Needs more info on C++17 compliance - particularly `noexecpt`.
2017-04-18 10:14:26 +01:00
Daniel James 8c9080f11f Document changes to allocator use 2017-04-18 10:14:26 +01:00
Daniel James ef05493c83 Test that construct/destroy aren't used when C++11 isn't available 2017-04-18 10:14:26 +01:00
Daniel James 7a0a598649 Don't track construction when using boost::tuple
Because it doesn't quiet work on C++11 compilers onwards.
2017-04-18 10:14:26 +01:00
Daniel James cafd236a18 Test more memory tracking 2017-04-18 10:14:26 +01:00
Daniel James e0054c7dd0 Remove alloc parameter from construct_value 2017-04-18 10:14:26 +01:00
Daniel James 3414e6628a Use allocator to construct/destroy nodes 2017-04-18 10:14:26 +01:00
Daniel James 08ce2c98e0 Rename call_construct to construct_value 2017-04-18 10:14:26 +01:00
Daniel James 6d79a322e2 Use macros to reduce call chain 2017-04-18 10:14:26 +01:00
Daniel James 9e70680044 Bypass construct_value/call_destroy_in a few places 2017-04-18 10:14:26 +01:00
Daniel James 7de8c91301 Remove calls to const_cast_pointer
It was needed because std::allocator_traits::construct doesn't work with
a const pointer (e.g. pointer to the first member of a std::pair). But
now we're only calling construct if BOOST_UNORDERED_CXX11_CONSTRUCTION
is true, so the allocator_traits::construct is no longer used here.
2017-04-18 10:14:26 +01:00
Daniel James c333a7f9fc Use piecewise construction where possible 2017-04-18 10:14:26 +01:00
Daniel James bc36a06a2d Comment about call_construct 2017-04-18 10:14:26 +01:00
Daniel James e62ac22f0b Replace BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT with BOOST_UNORDERED_CXX11_CONSTRUCTION
Require good construct support and piecewise construction. I don't know
if there are any platforms with good construct support, but no piecewise
construction, if there are then they'll no longer use
'allocator_traits::construct'/'allocator_traits::destruct'.
2017-04-18 10:14:26 +01:00
Daniel James 1092c972c9 Use allocator_traits to construct/destruct buckets 2017-04-18 10:14:26 +01:00
Daniel James 7e5520f974 Increase template depth for GCC
This appears to be an unavoidable problem with GCC's tuple
implementation. For example:

http://stackoverflow.com/q/23374953/2434

Appears to be okay in later versions of GCC though.
2017-04-18 10:14:26 +01:00
Daniel James 2b01bdbc25 More general deprecated check
`__has_cpp_attribute(deprecated)` returns true for C++11, but then warns
that it's a C++14 attribute, so only check in C++14 mode.
2017-04-16 16:34:22 +01:00
Daniel James 64a3be7d3e Use aligned_storage's address method to get pointer 2017-04-16 10:37:10 +01:00
Daniel James c0e03c3640 Add some more details to change log 2017-04-15 20:52:00 +01:00
Daniel James ed8c0f9ecd Add deprecated attributes to deprecated functions 2017-04-15 17:35:09 +01:00
Daniel James 2bfc59c461 Make node_handler constructor private + additional compile tests 2017-04-15 17:35:09 +01:00
Daniel James 727e36e6a6 Comment about clear_buckets/create_buckets awkwardness.
They both leave the container in an invalid state that needs to be
cleaned up immediately. This confused me slightly.
2017-04-15 17:35:09 +01:00
Daniel James 09bddd8df4 Clear buckets before deleting nodes in clear.
The order shouldn't really matter as nothing throws an exception, but it
seems cleaner to never have any dangling pointers.
2017-04-15 17:35:08 +01:00
Daniel James f089adc160 Change get_key to have node parameter 2017-04-15 17:35:08 +01:00
Daniel James 97b68ea05e Rename (grouped_)table_impl to table_unique/equiv
The old names don't make sense any more as either style can be used for
containers with equivalent keys, due to the use of node_algo.
2017-04-15 17:35:08 +01:00
Daniel James 972ac220f5 Add missing insert(P&&) methods to unordered_map/unordered_multimap 2017-04-15 17:35:08 +01:00
Daniel James 5d98f3d0f0 Noexcept specs for swap free functions 2017-04-15 17:35:08 +01:00
Daniel James 51cd1cd2af Some more typos 2017-04-12 08:25:14 +01:00
Daniel James 7e940e6e45 Fix some typos 2017-04-12 08:01:10 +01:00
Daniel James 2f4d286a51 Merge branch 'feature/doc-clarification' into develop 2017-04-11 23:40:48 +01:00
Daniel James c2d2be021a Don't test inserting from initializer list in old clang
There's a problem with it causing an ambiguous overload. I don't think
there's anything we can do to fix that, so just don't test it.

There's another bug where a std::pair doesn't get correctly constructed
from an rvalue when using Clang 3.1 in C++11 mode. But I can't see any
way to easily fix that, and it's a pretty old compiler now.
2017-04-08 06:17:43 +01:00
97 changed files with 17532 additions and 15062 deletions
+32
View File
@@ -0,0 +1,32 @@
# Copyright 2017 Daniel James
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
version: 1.0.{build}-{branch}
shallow_clone: true
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-10.0,msvc-11.0,msvc-12.0,msvc-14.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
install:
- set BOOST_ROOT=c:\projects\boost
- cd c:\projects\
- python %APPVEYOR_BUILD_FOLDER%\ci\download-boost-snapshot.py master
- rd /s /q %BOOST_ROOT%\boost\unordered
- cd %BOOST_ROOT%\tools\build
- cmd /c bootstrap
- cd %APPVEYOR_BUILD_FOLDER%
- echo. 2>Jamroot.jam
build: off
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\test
- cmd /c %BOOST_ROOT%\tools\build\b2 -j 3 toolset=%TOOLSET% include=%APPVEYOR_BUILD_FOLDER%\include include=%BOOST_ROOT%
+7
View File
@@ -0,0 +1,7 @@
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
[*.?pp]
indent_size = 2
+55 -34
View File
@@ -11,56 +11,77 @@ language: c++
addons:
apt:
packages:
- libboost-tools-dev
- libxml2-utils
- g++-multilib
matrix:
include:
- compiler: gcc
env: BJAM_TOOLSET=gcc
env: |
label="gcc C++03/11";
user_config="using gcc : : g++-4.8 --coverage -fsanitize=address ;"
enable_coverage=1
CXXSTD=03,11
- compiler: gcc
env: BJAM_TOOLSET=gcc-std11
#- compiler: gcc
# env: BJAM_TOOLSET=gcc-m32
- 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 ;"
CXXSTD=11
- compiler: clang
env: BJAM_TOOLSET=clang-std11
env: |
label="clang C++11/17";
user_config="using clang : : clang++ -fsanitize=address ;"
CXXSTD=11,17
# 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 ;"
CXXSTD=03
before_install:
- if [ -n $enable_coverage ]; then pip install --user cpp-coveralls; fi
before_script:
- export BOOST_VERSION=1.67.0
- export BOOST_FILENAME=boost_1_67_0
- export BOOST_ROOT=${HOME}/boost
- 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
- tar -xjf boost.tar.bz2
- mv boost_1_63_0 boost
- rm -r boost/boost/unordered
- |
# Pick snapshot to use
if [ "$TRAVIS_EVENT_TYPE" == "cron" ]
then
if [ "$TRAVIS_BRANCH" == "master" ]
then
snapshot=master
else
snapshot=develop
fi
else
#snapshot=stable
snapshot=master
fi
# Download and extract snapshot
echo "Downloading ${download_url}"
mkdir $HOME/download
cd $HOME/download
python ${TRAVIS_BUILD_DIR}/ci/download-boost-snapshot.py $snapshot
mv * ${BOOST_ROOT}
- rm -r ${BOOST_ROOT}/boost/unordered
- cd ${BOOST_ROOT}/tools/build
- mkdir ${HOME}/opt
- bash bootstrap.sh
- ./b2 install --prefix=$HOME/opt
after_success:
if [ -n $enable_coverage ]; then coveralls -r ${TRAVIS_BUILD_DIR} -b ${TRAVIS_BUILD_DIR}/test --gcov-options '\-lp' --include include/boost/unordered/ ; fi
script:
- cd ${TRAVIS_BUILD_DIR}/test
- bjam ${BJAM_TOOLSET} include=${HOME}/boost include=${TRAVIS_BUILD_DIR}/include
- ${HOME}/opt/bin/b2 -j 3 cxxstd=$CXXSTD -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include
- xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml
+6 -5
View File
@@ -3,16 +3,17 @@
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# Using clang format 3.8
# http://llvm.org/releases/3.8.0/tools/clang/docs/ClangFormatStyleOptions.html
# Using clang format 4.0
# http://llvm.org/releases/4.0.0/tools/clang/docs/ClangFormatStyleOptions.html
# Becuase you have to start somewhere.
BasedOnStyle: LLVM
# Basic settings
ColumnLimit: 80
ContinuationIndentWidth: 4
IndentWidth: 4
NamespaceIndentation: All
ContinuationIndentWidth: 2
IndentWidth: 2
UseTab: Never
Language: Cpp
Standard: Cpp03
@@ -34,4 +35,4 @@ BraceWrapping:
PointerAlignment: Left
# Boost specific stuff
ForEachMacros: [ BOOST_FOREACH ]
ForEachMacros: [ BOOST_FOREACH, UNORDERED_AUTO_TEST ]
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python
import urllib, os, os.path, sys, json, tarfile, zipfile, tempfile
def download(snapshot):
if snapshot == 'stable':
# TODO: Default version/filename if not available?
downloads = [
"https://sourceforge.net/projects/boost/files/boost/%s/%s.tar.bz2/download" %
(os.environ['BOOST_VERSION'], os.environ['BOOST_FILENAME'])]
else:
json_response = urllib.urlopen('https://api.bintray.com/packages/boostorg/%s/snapshot/files' % (snapshot))
x = json.load(json_response)
extension_priorities = { '.bz2': 2, '.gz': 1, '.zip': 0 }
file_list = []
version_dates = {}
for file in x:
file_extension = os.path.splitext(file['path'])[1]
if (file_extension in extension_priorities):
file['priority'] = extension_priorities[file_extension]
file_list.append(file)
if not file['version'] in version_dates or file['created'] < version_dates[file['version']]:
version_dates[file['version']] = file['created']
file_list.sort(key=lambda x: (version_dates[x['version']], x['priority']), reverse=True)
downloads = ['http://dl.bintray.com/boostorg/%s/%s' % (snapshot, file['path']) for file in file_list]
filename = ''
for download_url in downloads:
try:
print "Downloading: " + download_url
(filename, headers) = urllib.urlretrieve(download_url)
print "Extracting: " + filename
dir = tempfile.mkdtemp()
extract(filename, dir)
os.remove(filename)
files = os.listdir(dir)
assert(len(files) == 1)
os.rename(os.path.join(dir, files[0]), 'boost')
return
except IOError:
print "Error opening URL: " + download_url
def extract(filename, path = '.'):
if (filename.endswith(".gz")):
tar = tarfile.open(filename, "r:gz")
tar.extractall(path)
tar.close
elif (filename.endswith(".bz2")):
tar = tarfile.open(filename, "r:bz2")
tar.extractall(path)
tar.close
elif (filename.endswith(".zip")):
zip = zipfile.ZipFile(filename, "r")
zip.extractall(path)
zip.close
else:
assert False
if len(sys.argv) == 1:
download('stable')
elif len(sys.argv) == 2:
download(sys.argv[1])
else:
print "Usage: %s [stable|branch-name]" % (sys.argv[0])
+5 -1
View File
@@ -9,7 +9,9 @@ using quickbook ;
path-constant images_location : ../ ;
path-constant admonishment_location : ../../../../doc/src/images ;
xml unordered : unordered.qbk ;
xml unordered : unordered.qbk :
<xsl:param>generate.consistent.ids=1 ;
boostbook standalone : unordered :
<xsl:param>chunk.first.sections=1
<xsl:param>chunk.section.depth=2
@@ -21,6 +23,8 @@ boostbook standalone : unordered :
<xsl:param>boost.compact.function=0
<xsl:param>boost.compact.enum=0
<xsl:param>generate.consistent.ids=1
# HTML Options:
<format>html:<xsl:param>boost.root=../../../..
+7 -10
View File
@@ -17,7 +17,7 @@ the hash function, `Hash`, to the element's key (for `unordered_set` and
`unordered_multiset` the key is the whole element, but is referred to as the key
so that the same terminology can be used for sets and maps). This returns a
value of type `std::size_t`. `std::size_t` has a much greater range of values
then the number of buckets, so that container applies another transformation to
then the number of buckets, so the container applies another transformation to
that value to choose a bucket to place the element in.
Retrieving the elements for a given key is simple. The same process is applied
@@ -57,7 +57,7 @@ keep collisions to a minimum.
</row>
<row>
<entry>'''`size_type bucket(key_type const& k) const`'''</entry>
<entry>'''Returns the index of the bucket which would contain k'''</entry>
<entry>'''Returns the index of the bucket which would contain `k`.'''</entry>
</row>
<row>
<entry>'''`local_iterator begin(size_type n);`'''</entry>
@@ -92,7 +92,7 @@ You can also tell the container to change the bucket count (if required) by
calling `rehash`.
The standard leaves a lot of freedom to the implementer to decide how the
number of buckets are chosen, but it does make some requirements based on the
number of buckets is chosen, but it does make some requirements based on the
container's 'load factor', the average number of elements per bucket.
Containers also have a 'maximum load factor' which they should try to keep the
load factor below.
@@ -138,7 +138,7 @@ or close to the hint - unless your hint is unreasonably small or large.
]
[
[`void rehash(size_type n)`]
[Changes the number of buckets so that there at least n buckets, and
[Changes the number of buckets so that there at least `n` buckets, and
so that the load factor is less than the maximum load factor.]
]
@@ -149,7 +149,7 @@ or close to the hint - unless your hint is unreasonably small or large.
It is not specified how member functions other than `rehash` affect
the bucket count, although `insert` is only allowed to invalidate iterators
when the insertion causes the load factor to be greater than or equal to the
maximum load factor. For most implementations this means that insert will only
maximum load factor. For most implementations this means that `insert` will only
change the number of buckets when this happens. While iterators can be
invalidated by calls to `insert` and `rehash`, pointers and references to the
container's elements are never invalidated.
@@ -160,12 +160,9 @@ the expensive rehashing out of the way and let you store iterators, safe in
the knowledge that they won't be invalidated. If you are inserting `n`
elements into container `x`, you could first call:
x.rehash((x.size() + n) / x.max_load_factor() + 1);
x.rehash((x.size() + n) / x.max_load_factor());
[blurb Note: `rehash`'s argument is the minimum number of buckets, not the
number of elements, which is why the new size is divided by the maximum load factor. The
`+ 1` guarantees there is no invalidation; without it, reallocation could occur
if the number of bucket exactly divides the target size, since the container is
allowed to rehash when the load factor is equal to the maximum load factor.]
number of elements, which is why the new size is divided by the maximum load factor.]
[endsect]
+51 -6
View File
@@ -6,6 +6,8 @@
[template ticket[number]'''<ulink
url="https://svn.boost.org/trac/boost/ticket/'''[number]'''">'''#[number]'''</ulink>''']
[template pull_request[number][@https://github.com/boostorg/unordered/pull/[number] GitHub #[number]]]
[section:changes Change Log]
[h2 Review Version]
@@ -52,7 +54,7 @@ First official release.
Document that the equality and inequality operators are undefined for two
objects if their equality predicates aren't equivalent. Thanks to Daniel
Krügler.
* [@https://svn.boost.org/trac/boost/ticket/1710 Ticket 1710]:
* [@https://svn.boost.org/trac/boost/ticket/1710 Ticket 1710]:
Use a larger prime number list. Thanks to Thorsten Ottosen and Hervé
Brönnimann.
* Use
@@ -99,13 +101,13 @@ 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.
* Buckets are allocated lazily which means that constructing an empty container
will not allocate any memory.
[h2 Boost 1.42.0]
* Support instantiating the containers with incomplete value types.
@@ -170,7 +172,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 +209,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 +309,52 @@ 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.
[h2 Boost 1.66.0]
* Simpler move construction implementation.
* Documentation fixes ([pull_request 6]).
[h2 Boost 1.67.0]
* Improved C++17 support:
* Add template deduction guides from the standard.
* Use a simple implementation of `optional` in node handles, so
that they're closer to the standard.
* Add missing `noexcept` specifications to `swap`, `operator=`
and node handles, and change the implementation to match.
Using `std::allocator_traits::is_always_equal`, or our own
implementation when not available, and
`boost::is_nothrow_swappable` in the implementation.
* Improved C++20 support:
* Use `boost::to_address`, which has the proposed C++20 semantics,
rather than the old custom implementation.
* Add `element_type` to iterators, so that `std::pointer_traits`
will work.
* Use `std::piecewise_construct` on recent versions of Visual C++,
and other uses of the Dinkumware standard library,
now using Boost.Predef to check compiler and library versions.
* Use `std::iterator_traits` rather than the boost iterator traits
in order to remove dependency on Boost.Iterator.
* Remove iterators' inheritance from `std::iterator`, which is
deprecated in C++17, thanks to Daniela Engert
([@https://github.com/boostorg/unordered/pull/7 PR#7]).
* Stop using `BOOST_DEDUCED_TYPENAME`.
* Update some Boost include paths.
* Rename some internal methods, and variables.
* Various testing improvements.
* Miscellaneous internal changes.
[endsect]
+1 -1
View File
@@ -60,7 +60,7 @@
[Iterators iterate through the container in the order defined by
the comparison object.]
[Iterators iterate through the container in an arbitrary order, that
can change as elements are inserted. Although, equivalent elements
can change as elements are inserted, although equivalent elements
are always adjacent.]
]
[
+32 -16
View File
@@ -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 imperfect)
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
@@ -101,7 +117,7 @@ first part of the pair, and the remaining for the second part.
When swapping, `Pred` and `Hash` are not currently swapped by calling
`swap`, their copy constructors are used. As a consequence when swapping
an exception may be throw from their copy constructor.
an exception may be thrown from their copy constructor.
Variadic constructor arguments for `emplace` are only used when both
rvalue references and variadic template parameters are available.
+1 -1
View File
@@ -84,7 +84,7 @@ can be in any order. For example, it might be:
one,1
three,3
To store an object in an unordered associative container requires both an
To store an object in an unordered associative container requires both a
key equality function and a hash function. The default function objects in
the standard containers support a few basic types including integer types,
floating point types, pointer types, and the standard strings. Since
+4 -4
View File
@@ -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]
@@ -23,7 +23,7 @@ standard pretty much requires that the hash table uses chained addressing.
It would be conceivable to write a hash table that uses another method. For
example, it could use open addressing, and use the lookup chain to act as a
bucket but there are a some serious problems with this:
bucket but there are some serious problems with this:
* The draft standard requires that pointers to elements aren't invalidated, so
the elements can't be stored in one array, but will need a layer of
@@ -89,7 +89,7 @@ is that the required modulus operation is fairly expensive. This is what the
containers do in most cases.
Using a power of 2 allows for much quicker selection of the bucket
to use, but at the expense of loosing the upper bits of the hash value.
to use, but at the expense of losing the upper bits of the hash value.
For some specially designed hash functions it is possible to do this and
still get a good result but as the containers can take arbitrary hash
functions this can't be relied on.
@@ -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.
+5 -14
View File
@@ -1672,20 +1672,11 @@ function echo_node_handle_docs($map)
<classname>unordered_multi<?php echo $type ?></classname>, that
can then be inserted into a compatible container type.
</para>
<notes>
<para>
The name and template parameters of this type is implementation
defined, and should be obtained using the <code>node_type</code>
member typedef from the appropriate container.
</para>
<para>
In this version of Boost, <code>node_type</code> is different
for <?php echo $map ?
'<code>unordered_map</code> and <code>unordered_multimap</code>,' :
'<code>unordered_set</code> and <code>unordered_multiset</code>,';
?> this will be fixed in a future version of Boost.
</para>
</notes>
<para>
The name and template parameters of this type are implementation
defined, and should be obtained using the <code>node_type</code>
member typedef from the appropriate container.
</para>
</purpose>
<?php if ($map): ?>
<typedef name="key_type">
+10 -22
View File
@@ -2840,17 +2840,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<classname>unordered_multiset</classname>, that
can then be inserted into a compatible container type.
</para>
<notes>
<para>
The name and template parameters of this type is implementation
defined, and should be obtained using the <code>node_type</code>
member typedef from the appropriate container.
</para>
<para>
In this version of Boost, <code>node_type</code> is different
for <code>unordered_set</code> and <code>unordered_multiset</code>, this will be fixed in a future version of Boost.
</para>
</notes>
<para>
The name and template parameters of this type are implementation
defined, and should be obtained using the <code>node_type</code>
member typedef from the appropriate container.
</para>
</purpose>
<typedef name="value_type">
<type>typename Container::value_type></type>
@@ -5816,17 +5810,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<classname>unordered_multimap</classname>, that
can then be inserted into a compatible container type.
</para>
<notes>
<para>
The name and template parameters of this type is implementation
defined, and should be obtained using the <code>node_type</code>
member typedef from the appropriate container.
</para>
<para>
In this version of Boost, <code>node_type</code> is different
for <code>unordered_map</code> and <code>unordered_multimap</code>, this will be fixed in a future version of Boost.
</para>
</notes>
<para>
The name and template parameters of this type are implementation
defined, and should be obtained using the <code>node_type</code>
member typedef from the appropriate container.
</para>
</purpose>
<typedef name="key_type">
<type>typename Container::key_type</type>
+1 -1
View File
@@ -4,7 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered_map.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include "../../examples/fnv1.hpp"
+1 -1
View File
@@ -4,7 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered_set.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/core/lightweight_test.hpp>
//[point_example1
struct point {
+1 -1
View File
@@ -5,7 +5,7 @@
#include <boost/unordered_set.hpp>
#include <boost/functional/hash.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/core/lightweight_test.hpp>
//[point_example2
struct point {
+2 -1
View File
@@ -3,7 +3,8 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[library Boost.Unordered
[quickbook 1.5]
[quickbook 1.7]
[compatibility-mode 1.5]
[authors [James, Daniel]]
[copyright 2003 2004 Jeremy B. Maitin-Shepard]
[copyright 2005 2006 2007 2008 Daniel James]
+1 -1
View File
@@ -4,7 +4,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./case_insensitive.hpp"
#include <boost/detail/lightweight_test.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/unordered_map.hpp>
struct word_info {
+18 -12
View File
@@ -11,6 +11,8 @@
#pragma once
#endif
#include <boost/predef.h>
#if defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
// Already defined.
#elif defined(BOOST_LIBSTDCXX11)
@@ -18,20 +20,24 @@
#if BOOST_LIBSTDCXX_VERSION > 40600
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#elif defined(_LIBCPP_VERSION)
#elif BOOST_LIB_STD_CXX
// https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206
#if LIBCPP_VERSION >= 3000
#if BOOST_LIB_STD_CXX >= BOOST_VERSION_NUMBER(3, 0, 0)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#elif defined(BOOST_MSVC)
#elif defined(BOOST_LIB_STD_DINKUMWARE)
// Apparently C++11 standard supported in Visual Studio 2012
// https://msdn.microsoft.com/en-us/library/hh567368.aspx#stl
// 2012 = VC+11 = BOOST_MSVC 1700 Hopefully!
#if BOOST_MSVC >= 1700
// I have no idea when Dinkumware added it, probably a lot
// earlier than this check.
#if BOOST_LIB_STD_DINKUMWARE >= BOOST_VERSION_NUMBER(6, 50, 0) || \
BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(17, 0, 0)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1
#endif
#endif
// Assume that an unknown library does not support piecewise construction.
#if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT)
#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 0
#endif
@@ -41,17 +47,17 @@
#endif
namespace boost {
namespace unordered {
namespace unordered {
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
using std::piecewise_construct_t;
using std::piecewise_construct;
using std::piecewise_construct_t;
using std::piecewise_construct;
#else
struct piecewise_construct_t
{
};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
struct piecewise_construct_t
{
};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
#endif
}
}
}
#endif
File diff suppressed because it is too large Load Diff
+48 -88
View File
@@ -7,101 +7,61 @@
#include <boost/unordered/unordered_map_fwd.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;
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 std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K const const_key_type;
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;
typedef
typename ::boost::unordered::detail::rebind_wrap<A, value_type>::type
value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
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::pick_node<A, 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<value_type> extractor;
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 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::iterator<node> iterator;
typedef boost::unordered::iterator_detail::c_iterator<node> c_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;
};
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;
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_map
{
typedef boost::unordered_map<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
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
{
typedef boost::unordered_map<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_multimap
{
typedef boost::unordered_multimap<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}
template <typename K, typename M, typename H, typename P, typename A>
class instantiate_multimap
{
typedef boost::unordered_multimap<K, M, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}
}
+47 -86
View File
@@ -7,99 +7,60 @@
#include <boost/unordered/unordered_set_fwd.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;
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 T value_type;
typedef H hasher;
typedef P key_equal;
typedef T const const_key_type;
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;
typedef
typename ::boost::unordered::detail::rebind_wrap<A, value_type>::type
value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
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::pick_node<A, 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 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 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::c_iterator<node> iterator;
typedef boost::unordered::iterator_detail::c_iterator<node> c_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;
};
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;
template <typename T, typename H, typename P, typename A>
class instantiate_set
{
typedef boost::unordered_set<T, H, P, A> container;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
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;
container x;
typename container::node_type node_type;
typename container::insert_return_type insert_return_type;
};
template <typename T, typename H, typename P, typename A>
class instantiate_multiset
{
typedef boost::unordered_multiset<T, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}
template <typename T, typename H, typename P, typename A>
class instantiate_multiset
{
typedef boost::unordered_multiset<T, H, P, A> container;
container x;
typename container::node_type node_type;
};
}
}
}
File diff suppressed because it is too large Load Diff
+37 -34
View File
@@ -17,45 +17,48 @@
#include <memory>
namespace boost {
namespace unordered {
template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
namespace unordered {
template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_map;
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 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>&);
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 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>& 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>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap;
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 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>&);
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 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>& 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;
}
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;
}
using boost::unordered::unordered_map;
using boost::unordered::unordered_multimap;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
using boost::unordered::unordered_map;
using boost::unordered::unordered_multimap;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
}
#endif
File diff suppressed because it is too large Load Diff
+35 -32
View File
@@ -17,43 +17,46 @@
#include <memory>
namespace boost {
namespace unordered {
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
namespace unordered {
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_set;
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 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);
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 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)
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> >
class unordered_multiset;
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
template <class T, class H, class P, class A>
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 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);
template <class T, class H, class P, class A>
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 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)
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;
}
template <class N, class T, class A> class node_handle_set;
template <class N, class T, class A> struct insert_return_type_set;
}
using boost::unordered::unordered_set;
using boost::unordered::unordered_multiset;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
using boost::unordered::unordered_set;
using boost::unordered::unordered_multiset;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
}
#endif
+44
View File
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017-2018 Daniel James
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
-->
<explicit-failures-markup>
<!-- unordered -->
<library name="unordered">
<mark-expected-failures>
<test name="unnecessary_copy_tests"/>
<toolset name="borland-*"/>
<toolset name="sun-*"/>
<note author="Daniel James">
This tests whether inserting elements creates as few copies as I think
is possible. If this fails it just means that the container might be
a little inefficient.
</note>
</mark-expected-failures>
<mark-expected-failures>
<test name="compile_map_unordered_allocator"/>
<toolset name="msvc-7.1"/>
<note author="Daniel James">
This test fail because it's using unordered's internal
allocator traits, which doesn't work on Visual C++ 7.1.
It normally uses the one from Boost.Container by default.
</note>
</mark-expected-failures>
<mark-expected-failures>
<test name="noexcept_tests"/>
<toolset name="gcc-4.3c+"/>
<note author="Daniel James">
boost::is_nothrow_move_constructible and
boost::is_nothrow_move_assignable don't seem to work on this
compiler. I'd hope that anyone wanting noexcept support would
use a more recent compiler anyway.
</note>
</mark-expected-failures>
</library>
</explicit-failures-markup>
+5 -1
View File
@@ -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,8 @@ 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/deduction_tests.cpp ]
[ run unordered/compile_set.cpp : :
: <define>BOOST_UNORDERED_USE_MOVE
@@ -90,4 +93,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 ]
;
+113 -66
View File
@@ -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
@@ -16,16 +17,27 @@ test::seed_t initialize_seed(12847);
template <class T> struct self_assign_base : public test::exception_base
{
test::random_values<T> values;
self_assign_base(std::size_t count = 0) : values(count) {}
test::random_values<T> values;
self_assign_base(std::size_t count = 0) : values(count, test::limited_range)
{
}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const { x = x; }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
test::check_equivalent_keys(x);
}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const
{
x = x;
DISABLE_EXCEPTIONS;
test::check_container(x, values);
test::check_equivalent_keys(x);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
test::check_equivalent_keys(x);
}
};
template <class T> struct self_assign_test1 : self_assign_base<T>
@@ -34,105 +46,140 @@ template <class T> struct self_assign_test1 : self_assign_base<T>
template <class T> struct self_assign_test2 : self_assign_base<T>
{
self_assign_test2() : self_assign_base<T>(100) {}
self_assign_test2() : self_assign_base<T>(100) {}
};
template <class T> struct assign_base : public test::exception_base
{
test::random_values<T> x_values, y_values;
T x, y;
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;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::allocator_type allocator_type;
assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: x_values(), y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
}
assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: x_values(), y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
}
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const { x1 = y; }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{
test::check_equivalent_keys(x1);
typedef T data_type;
T init() const { return T(x); }
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of
// messing up the data.
if (x_values.size()) {
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
}
void run(T& x1) const
{
x1 = y;
DISABLE_EXCEPTIONS;
test::check_container(x1, y_values);
test::check_equivalent_keys(x1);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{
test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of
// messing up the data.
if (x_values.size()) {
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
}
}
};
template <class T> struct assign_values : assign_base<T>
{
assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2,
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());
}
assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2,
test::random_generator gen = test::default_generator, float mlf1 = 1.0,
float mlf2 = 1.0)
: assign_base<T>(tag1, tag2, mlf1, mlf2)
{
this->x_values.fill(count1, gen);
this->y_values.fill(count2, gen);
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
template <class T> struct assign_test1 : assign_values<T>
{
assign_test1() : assign_values<T>(0, 0, 0, 0) {}
assign_test1() : assign_values<T>(0, 0, 0, 0) {}
};
template <class T> struct assign_test2 : assign_values<T>
{
assign_test2() : assign_values<T>(60, 0, 0, 0) {}
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) {}
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) {}
assign_test4() : assign_values<T>(10, 10, 1, 2) {}
};
template <class T> struct assign_test4a : assign_values<T>
{
assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
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>
{
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());
}
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_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()
+130 -88
View File
@@ -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&) {}
@@ -14,157 +16,197 @@ test::seed_t initialize_seed(91274);
struct objects
{
test::exception::object obj;
test::exception::hash hash;
test::exception::equal_to equal_to;
test::exception::allocator<test::exception::object> allocator;
test::exception::object obj;
test::exception::hash hash;
test::exception::equal_to equal_to;
test::exception::allocator<test::exception::object> allocator;
};
template <class T> struct construct_test1 : public objects, test::exception_base
{
void run() const
{
T x;
avoid_unused_warning(x);
}
void run() const
{
T x;
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
};
template <class T> struct construct_test2 : public objects, test::exception_base
{
void run() const
{
T x(300);
avoid_unused_warning(x);
}
void run() const
{
T x(300);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
};
template <class T> struct construct_test3 : public objects, test::exception_base
{
void run() const
{
T x(0, hash);
avoid_unused_warning(x);
}
void run() const
{
T x(0, hash);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
};
template <class T> struct construct_test4 : public objects, test::exception_base
{
void run() const
{
T x(0, hash, equal_to);
avoid_unused_warning(x);
}
void run() const
{
T x(0, hash, equal_to);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
};
template <class T> struct construct_test5 : public objects, test::exception_base
{
void run() const
{
T x(50, hash, equal_to, allocator);
avoid_unused_warning(x);
}
void run() const
{
T x(50, hash, equal_to, allocator);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
};
template <class T> struct construct_test6 : public objects, test::exception_base
{
void run() const
{
T x(allocator);
avoid_unused_warning(x);
}
void run() const
{
T x(allocator);
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
};
template <class T> struct range : public test::exception_base
{
test::random_values<T> values;
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
{
void run() const
{
T x(this->values.begin(), this->values.end());
avoid_unused_warning(x);
}
void run() const
{
T x(this->values.begin(), this->values.end());
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct range_construct_test2 : public range<T>, objects
{
void run() const
{
T x(this->values.begin(), this->values.end(), 0);
avoid_unused_warning(x);
}
void run() const
{
T x(this->values.begin(), this->values.end(), 0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct range_construct_test3 : public range<T>, objects
{
void run() const
{
T x(this->values.begin(), this->values.end(), 0, hash);
avoid_unused_warning(x);
}
void run() const
{
T x(this->values.begin(), this->values.end(), 0, hash);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct range_construct_test4 : public range<T>, objects
{
void run() const
{
T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
avoid_unused_warning(x);
}
void run() const
{
T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
// Need to run at least one test with a fairly large number
// of objects in case it triggers a rehash.
template <class T> struct range_construct_test5 : public range<T>, objects
{
range_construct_test5() : range<T>(60) {}
range_construct_test5() : range<T>(60) {}
void run() const
{
T x(this->values.begin(), this->values.end(), 0, hash, equal_to,
allocator);
avoid_unused_warning(x);
}
void run() const
{
T x(this->values.begin(), this->values.end(), 0, hash, equal_to, allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct input_range_construct_test : public range<T>, objects
{
input_range_construct_test() : range<T>(60) {}
input_range_construct_test() : range<T>(60) {}
void run() const
{
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
begin = this->values.begin(),
end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end), 0, hash,
equal_to, allocator);
avoid_unused_warning(x);
}
void run() const
{
typename test::random_values<T>::const_iterator begin =
this->values.begin(),
end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end), 0, hash,
equal_to, allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct copy_range_construct_test : public range<T>, objects
{
copy_range_construct_test() : range<T>(60) {}
copy_range_construct_test() : range<T>(60) {}
void run() const
{
T x(test::copy_iterator(this->values.begin()),
test::copy_iterator(this->values.end()), 0, hash, equal_to,
allocator);
avoid_unused_warning(x);
}
void run() const
{
T x(test::copy_iterator(this->values.begin()),
test::copy_iterator(this->values.end()), 0, hash, equal_to, allocator);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
// clang-format off
EXCEPTION_TESTS(
(construct_test1)(construct_test2)(construct_test3)(construct_test4)(
construct_test5)(construct_test6)(range_construct_test1)(
range_construct_test2)(range_construct_test3)(range_construct_test4)(
range_construct_test5)(input_range_construct_test)(
copy_range_construct_test),
CONTAINER_SEQ)
(construct_test1)(construct_test2)(construct_test3)(construct_test4)
(construct_test5)(construct_test6)(range_construct_test1)
(range_construct_test2)(range_construct_test3)(range_construct_test4)
(range_construct_test5)(input_range_construct_test)
(copy_range_construct_test),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+21 -21
View File
@@ -13,32 +13,32 @@
#include "../objects/exception.hpp"
typedef boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_set;
test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_set;
typedef boost::unordered_multiset<test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_multiset;
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_multiset;
typedef boost::unordered_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_map;
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_map;
typedef boost::unordered_multimap<test::exception::object,
test::exception::object, test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_multimap;
test::exception::object, test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_multimap;
typedef boost::unordered_set<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_pair_set;
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_pair_set;
typedef boost::unordered_multiset<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_pair_multiset;
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_pair_multiset;
#define CONTAINER_SEQ (test_set)(test_multiset)(test_map)(test_multimap)
#define CONTAINER_PAIR_SEQ \
(test_pair_set)(test_pair_multiset)(test_map)(test_multimap)
(test_pair_set)(test_pair_multiset)(test_map)(test_multimap)
+72 -32
View File
@@ -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&) {}
@@ -13,58 +15,96 @@ test::seed_t initialize_seed(73041);
template <class T> struct copy_test1 : public test::exception_base
{
T x;
T x;
void run() const
{
T y(x);
avoid_unused_warning(y);
}
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
BOOST_TEST(y.empty());
test::check_equivalent_keys(y);
}
};
template <class T> struct copy_test2 : public test::exception_base
{
test::random_values<T> values;
T x;
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);
}
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
}
};
template <class T> struct copy_test3 : public test::exception_base
{
test::random_values<T> values;
T x;
test::random_values<T> values;
T x;
copy_test3() : values(100), x(values.begin(), values.end()) {}
copy_test3() : values(100), x(values.begin(), values.end()) {}
void run() const
{
T y(x);
avoid_unused_warning(y);
}
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
}
};
template <class T> struct copy_test3a : public test::exception_base
{
test::random_values<T> values;
T x;
copy_test3a()
: values(100, test::limited_range), x(values.begin(), values.end())
{
}
void run() const
{
T y(x);
DISABLE_EXCEPTIONS;
test::check_container(y, this->values);
test::check_equivalent_keys(y);
}
};
template <class T> struct copy_with_allocator_test : public test::exception_base
{
test::random_values<T> values;
T x;
test::exception::allocator<test::exception::object> allocator;
test::random_values<T> values;
T x;
test::exception::allocator<test::exception::object> allocator;
copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {}
copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {}
void run() const
{
T y(x, allocator);
avoid_unused_warning(y);
}
void run() const
{
T y(x, allocator);
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()
+25 -20
View File
@@ -13,37 +13,42 @@ test::seed_t initialize_seed(835193);
template <class T> struct erase_test_base : public test::exception_base
{
test::random_values<T> values;
erase_test_base(unsigned int count = 5) : values(count) {}
test::random_values<T> values;
erase_test_base(unsigned int count = 5) : values(count, test::limited_range)
{
}
typedef T data_type;
typedef T data_type;
data_type init() const { return T(values.begin(), values.end()); }
data_type init() const { return T(values.begin(), values.end()); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
std::string scope(test::scope);
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
std::string scope(test::scope);
BOOST_TEST(scope.find("hash::") != std::string::npos ||
scope.find("equal_to::") != std::string::npos ||
scope == "operator==(object, object)");
BOOST_TEST(scope.find("hash::") != std::string::npos ||
scope.find("equal_to::") != std::string::npos ||
scope == "operator==(object, object)");
test::check_equivalent_keys(x);
}
test::check_equivalent_keys(x);
}
};
template <class T> struct erase_by_key_test1 : public erase_test_base<T>
{
void run(T& x) const
{
typedef BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
iterator;
void run(T& x) const
{
typedef typename test::random_values<T>::const_iterator iterator;
for (iterator it = this->values.begin(), end = this->values.end();
it != end; ++it) {
x.erase(test::get_key<T>(*it));
}
for (iterator it = this->values.begin(), end = this->values.end();
it != end; ++it) {
x.erase(test::get_key<T>(*it));
}
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
};
EXCEPTION_TESTS((erase_by_key_test1), CONTAINER_SEQ)
+362 -253
View File
@@ -2,306 +2,415 @@
// 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 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
{
std::string scope(test::scope);
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;
if (scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations);
test::check_equivalent_keys(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);
}
};
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class T> struct emplace_test1 : public insert_test_base<T>
struct insert_lvalue_type : inserter_base
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(*it);
}
} insert_lvalue;
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);
}
}
struct insert_lvalue_begin_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(x.begin(), *it);
}
} insert_lvalue_begin;
struct insert_lvalue_end_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(x.end(), *it);
}
} insert_lvalue_end;
template <typename T> struct insert_lvalue_pos_type_impl : inserter_base
{
typename T::iterator pos;
insert_lvalue_pos_type_impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{
pos = get_iterator(x.insert(pos, *it));
}
};
#endif
template <class T> struct insert_test1 : public insert_test_base<T>
struct insert_lvalue_pos_type
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
template <typename T>
friend insert_lvalue_pos_type_impl<T> generate(insert_lvalue_pos_type, T& x)
{
return insert_lvalue_pos_type_impl<T>(x);
}
} insert_lvalue_pos;
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);
}
}
struct insert_single_item_range_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert(it, test::next(it));
}
} insert_single_item_range;
struct emplace_lvalue_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace(*it);
}
} emplace_lvalue;
struct emplace_lvalue_begin_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace_hint(x.begin(), *it);
}
} emplace_lvalue_begin;
struct emplace_lvalue_end_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.emplace_hint(x.end(), *it);
}
} emplace_lvalue_end;
template <typename T> struct emplace_lvalue_pos_type_impl : inserter_base
{
typename T::iterator pos;
emplace_lvalue_pos_type_impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{
pos = get_iterator(x.emplace_hint(pos, *it));
}
};
template <class T> struct insert_test2 : public insert_test_base<T>
struct emplace_lvalue_pos_type
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
template <typename T>
friend emplace_lvalue_pos_type_impl<T> generate(emplace_lvalue_pos_type, T& x)
{
return emplace_lvalue_pos_type_impl<T>(x);
}
} emplace_lvalue_pos;
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);
}
// 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;
}
}
};
template <class T> struct insert_test3 : public insert_test_base<T>
struct map_insert_operator_type : map_inserter_base
{
void run(T& x) const { x.insert(this->values.begin(), this->values.end()); }
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x[it->first] = it->second;
}
} map_insert_operator;
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>
struct map_insert_or_assign_type : map_inserter_base
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
x.insert_or_assign(it->first, it->second);
}
} map_insert_or_assign;
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));
}
}
};
// 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
template <class T> struct insert_test_rehash1 : public insert_test_base<T>
// Range insert tests
template <typename T, typename Values>
void insert_range_exception_test_impl(T x, Values const& v)
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
test::ordered<T> tracker;
tracker.insert(x.begin(), x.end());
insert_test_rehash1() : insert_test_base<T>(1000) {}
try {
ENABLE_EXCEPTIONS;
x.insert(v.begin(), v.end());
} catch (...) {
test::check_equivalent_keys(x);
throw;
}
T init() const
{
using namespace std;
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
test::check_equivalent_keys(x);
tracker.insert(v.begin(), v.end());
tracker.compare(x);
}
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;
}
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_exception_test(T*, test::random_generator gen)
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
for (int i = 0; i < 5; ++i) {
test::random_values<T> v(10, gen);
T x;
void run(T& x, strong_type& strong) const
{
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
int count = 0;
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v));
}
}
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>
template <typename T>
void insert_range_rehash_exception_test(T*, test::random_generator gen)
{
BOOST_DEDUCED_TYPENAME T::size_type mutable rehash_bucket_count,
original_bucket_count;
for (int i = 0; i < 5; ++i) {
T x;
rehash_prep(x);
insert_test_rehash3() : insert_test_base<T>(1000) {}
test::random_values<T> v2(5, gen);
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v2));
}
}
T init() const
{
using namespace std;
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
// clang-format off
UNORDERED_TEST(insert_range_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
((default_generator)(limited_range)(generate_collisions))
)
T x;
x.max_load_factor(0.25);
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;
}
void run(T& x) const
{
BOOST_DEDUCED_TYPENAME T::size_type bucket_count = x.bucket_count();
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()
+108
View File
@@ -0,0 +1,108 @@
// Copyright 2017-2018 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/exception_test.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/metafunctions.hpp"
#include "../helpers/random_values.hpp"
#include "./containers.hpp"
template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y)
{
std::size_t size = x.size() + y.size();
try {
ENABLE_EXCEPTIONS;
x.merge(y);
} catch (...) {
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
throw;
}
// Not a full check, just want to make sure the merge completed.
BOOST_TEST(size == x.size() + y.size());
if (y.size()) {
BOOST_TEST(test::has_unique_keys<T1>::value);
for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
}
}
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
template <typename T1, typename T2>
void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12,
test::random_generator gen1, test::random_generator gen2)
{
std::size_t count1 = count12 / 256;
std::size_t count2 = count12 % 256;
int tag1 = tag12 / 256;
int tag2 = tag12 % 256;
test::random_values<T1> v1(count1, gen1);
test::random_values<T2> v2(count2, gen2);
T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1),
test::exception::equal_to(tag1));
T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2),
test::exception::equal_to(tag2));
EXCEPTION_LOOP(merge_exception_test(x, y))
}
boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_set_;
boost::unordered_multiset<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_multiset_;
boost::unordered_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_map_;
boost::unordered_multimap<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_multimap_;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
// clang-format off
UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
((test_set_)(test_multiset_))
((test_set_)(test_multiset_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0000)(0x0001)(0x0102))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
UNORDERED_MULTI_TEST(map_merge, merge_exception_test,
((test_map_)(test_multimap_))
((test_map_)(test_multimap_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0101)(0x0200)(0x0201))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
// Run fewer generate_collisions tests, as they're slow.
UNORDERED_MULTI_TEST(set_merge_collisions, merge_exception_test,
((test_set_)(test_multiset_))
((test_set_)(test_multiset_))
((0x0a0a))
((0x0202)(0x0100)(0x0201))
((generate_collisions))
((generate_collisions))
)
UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
((test_map_)(test_multimap_))
((test_map_)(test_multimap_))
((0x0a0a))
((0x0000)(0x0002)(0x0102))
((generate_collisions))
((generate_collisions))
)
// clang-format on
RUN_TESTS_QUIET()
+74 -65
View File
@@ -7,117 +7,126 @@
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include <iostream>
#include "../helpers/tracker.hpp"
#if defined(BOOST_MSVC)
#pragma warning( \
disable : 4512) // move_assignment operator could not be generated
disable : 4512) // move_assignment operator could not be generated
#endif
test::seed_t initialize_seed(12847);
template <class T> struct move_assign_base : public test::exception_base
{
test::random_values<T> x_values, y_values;
T x, y;
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;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::allocator_type allocator_type;
move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: x_values(), y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
}
move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: x_values(), y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{
x.max_load_factor(mlf1);
y.max_load_factor(mlf2);
}
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const
{
test::exceptions_enable disable_exceptions(false);
T y1 = y;
disable_exceptions.release();
x1 = boost::move(y1);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{
test::check_equivalent_keys(x1);
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const
{
test::exceptions_enable disable_exceptions(false);
T y1 = y;
disable_exceptions.release();
x1 = boost::move(y1);
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of
// messing up the data.
if (x_values.size()) {
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
}
DISABLE_EXCEPTIONS;
test::check_container(x1, y_values);
test::check_equivalent_keys(x1);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{
test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of
// messing up the data.
if (x_values.size()) {
T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2);
}
}
};
template <class T> struct move_assign_values : move_assign_base<T>
{
move_assign_values(unsigned int count1, unsigned int count2, int tag1,
int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: move_assign_base<T>(tag1, tag2, mlf1, mlf2)
{
this->x_values.fill(count1);
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());
}
move_assign_values(unsigned int count1, unsigned int count2, int tag1,
int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: move_assign_base<T>(tag1, tag2, mlf1, mlf2)
{
this->x_values.fill(count1, test::limited_range);
this->y_values.fill(count2, test::limited_range);
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
template <class T> struct move_assign_test1 : move_assign_values<T>
{
move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
};
template <class T> struct move_assign_test2 : move_assign_values<T>
{
move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
};
template <class T> struct move_assign_test3 : move_assign_values<T>
{
move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
};
template <class T> struct move_assign_test4 : move_assign_values<T>
{
move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
};
template <class T> struct move_assign_test4a : move_assign_values<T>
{
move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
};
template <class T> struct move_assign_test5 : move_assign_values<T>
{
move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
};
template <class T> struct equivalent_test1 : move_assign_base<T>
{
equivalent_test1() : move_assign_base<T>(0, 0)
{
test::random_values<T> x_values2(10);
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());
}
equivalent_test1() : move_assign_base<T>(0, 0)
{
test::random_values<T> x_values2(10, test::limited_range);
this->x_values.insert(x_values2.begin(), x_values2.end());
this->x_values.insert(x_values2.begin(), x_values2.end());
test::random_values<T> y_values2(10, test::limited_range);
this->y_values.insert(y_values2.begin(), y_values2.end());
this->y_values.insert(y_values2.begin(), y_values2.end());
this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end());
}
};
EXCEPTION_TESTS((move_assign_test1)(move_assign_test2)(move_assign_test3)(
move_assign_test4)(move_assign_test4a)(move_assign_test5)(
equivalent_test1),
CONTAINER_SEQ)
// clang-format off
EXCEPTION_TESTS(
(move_assign_test1)(move_assign_test2)(move_assign_test3)
(move_assign_test4)(move_assign_test4a)(move_assign_test5)
(equivalent_test1),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+88 -37
View File
@@ -8,75 +8,126 @@
#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
{
test::random_values<T> values;
unsigned int n;
rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
: values(count), n(n_)
{
}
test::random_values<T> values;
unsigned int n;
rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
: values(count, test::limited_range), n(n_)
{
}
typedef T data_type;
typedef test::strong<T> strong_type;
typedef T data_type;
typedef test::strong<T> strong_type;
data_type init() const
{
T x(values.begin(), values.end(), n);
return x;
}
data_type init() const
{
T x(values.begin(), values.end(), n);
return x;
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(
T const& x, strong_type const& strong) const
{
std::string scope(test::scope);
void check BOOST_PREVENT_MACRO_SUBSTITUTION(
T const& x, strong_type const& strong) const
{
std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos &&
scope.find("equal_to::operator()") == std::string::npos &&
scope != "operator==(object, object)")
strong.test(x);
if (scope.find("hash::operator()") == std::string::npos &&
scope.find("equal_to::operator()") == std::string::npos &&
scope != "operator==(object, object)")
strong.test(x);
test::check_equivalent_keys(x);
}
test::check_equivalent_keys(x);
}
};
template <class T> struct rehash_test0 : rehash_test_base<T>
{
rehash_test0() : rehash_test_base<T>(0) {}
void run(T& x) const { x.rehash(0); }
rehash_test0() : rehash_test_base<T>(0) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct rehash_test1 : rehash_test_base<T>
{
rehash_test1() : rehash_test_base<T>(0) {}
void run(T& x) const { x.rehash(200); }
rehash_test1() : rehash_test_base<T>(0) {}
void run(T& x) const
{
x.rehash(200);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct rehash_test2 : rehash_test_base<T>
{
rehash_test2() : rehash_test_base<T>(0, 200) {}
void run(T& x) const { x.rehash(0); }
rehash_test2() : rehash_test_base<T>(0, 200) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct rehash_test3 : rehash_test_base<T>
{
rehash_test3() : rehash_test_base<T>(10, 0) {}
void run(T& x) const { x.rehash(200); }
rehash_test3() : rehash_test_base<T>(10, 0) {}
void run(T& x) const
{
x.rehash(200);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct rehash_test4 : rehash_test_base<T>
{
rehash_test4() : rehash_test_base<T>(10, 200) {}
void run(T& x) const { x.rehash(0); }
rehash_test4() : rehash_test_base<T>(10, 200) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
template <class T> struct rehash_test5 : rehash_test_base<T>
{
rehash_test5() : rehash_test_base<T>(200, 10) {}
void run(T& x) const
{
x.rehash(0);
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
};
// clang-format off
EXCEPTION_TESTS(
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4),
CONTAINER_SEQ)
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4)
(rehash_test5),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+86 -65
View File
@@ -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
@@ -16,24 +17,33 @@ test::seed_t initialize_seed(9387);
template <class T> struct self_swap_base : public test::exception_base
{
test::random_values<T> values;
self_swap_base(std::size_t count = 0) : values(count) {}
test::random_values<T> values;
self_swap_base(std::size_t count = 0) : values(count, test::limited_range) {}
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const { x.swap(x); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
std::string scope(test::scope);
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
void run(T& x) const
{
x.swap(x);
test::check_equivalent_keys(x);
}
DISABLE_EXCEPTIONS;
test::check_container(x, this->values);
test::check_equivalent_keys(x);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{
std::string scope(test::scope);
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
test::check_equivalent_keys(x);
}
};
template <class T> struct self_swap_test1 : self_swap_base<T>
@@ -42,83 +52,94 @@ template <class T> struct self_swap_test1 : self_swap_base<T>
template <class T> struct self_swap_test2 : self_swap_base<T>
{
self_swap_test2() : self_swap_base<T>(100) {}
self_swap_test2() : self_swap_base<T>(100) {}
};
template <class T> struct swap_base : public test::exception_base
{
const test::random_values<T> x_values, y_values;
const T initial_x, initial_y;
const test::random_values<T> x_values, y_values;
const T initial_x, initial_y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
typedef typename T::hasher hasher;
typedef typename T::key_equal key_equal;
typedef typename T::allocator_type allocator_type;
swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
: x_values(count1), y_values(count2),
initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
key_equal(tag1), allocator_type(tag1)),
initial_y(
y_values.begin(), y_values.end(), 0, hasher(tag2),
key_equal(tag2),
allocator_type(
T::allocator_type::propagate_on_container_swap::value ? tag2
: tag1))
{
swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
: x_values(count1, test::limited_range),
y_values(count2, test::limited_range),
initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
key_equal(tag1), allocator_type(tag1)),
initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
key_equal(tag2),
allocator_type(T::allocator_type::propagate_on_container_swap::value
? tag2
: tag1))
{
}
struct data_type
{
data_type(T const& x_, T const& y_) : x(x_), y(y_) {}
T x, y;
};
data_type init() const { return data_type(initial_x, initial_y); }
void run(data_type& d) const
{
try {
d.x.swap(d.y);
} catch (std::runtime_error&) {
}
struct data_type
{
data_type(T const& x_, T const& y_) : x(x_), y(y_) {}
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);
}
T x, y;
};
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const
{
std::string scope(test::scope);
data_type init() const { return data_type(initial_x, initial_y); }
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
void run(data_type& d) const
{
try {
d.x.swap(d.y);
} catch (std::runtime_error) {
}
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const
{
std::string scope(test::scope);
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
test::check_equivalent_keys(d.x);
test::check_equivalent_keys(d.y);
}
test::check_equivalent_keys(d.x);
test::check_equivalent_keys(d.y);
}
};
template <class T> struct swap_test1 : swap_base<T>
{
swap_test1() : swap_base<T>(0, 0, 0, 0) {}
swap_test1() : swap_base<T>(0, 0, 0, 0) {}
};
template <class T> struct swap_test2 : swap_base<T>
{
swap_test2() : swap_base<T>(60, 0, 0, 0) {}
swap_test2() : swap_base<T>(60, 0, 0, 0) {}
};
template <class T> struct swap_test3 : swap_base<T>
{
swap_test3() : swap_base<T>(0, 60, 0, 0) {}
swap_test3() : swap_base<T>(0, 60, 0, 0) {}
};
template <class T> struct swap_test4 : swap_base<T>
{
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
};
EXCEPTION_TESTS((self_swap_test1)(self_swap_test2)(swap_test1)(swap_test2)(
swap_test3)(swap_test4),
CONTAINER_SEQ)
// clang-format off
EXCEPTION_TESTS(
(self_swap_test1)(self_swap_test2)
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
CONTAINER_SEQ)
// clang-format on
RUN_TESTS()
+6 -6
View File
@@ -11,23 +11,23 @@
#include <boost/type_traits/is_same.hpp>
namespace test {
template <class T1> struct check_return_type
{
template <class T1> struct check_return_type
{
template <class T2> static void equals(T2)
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2> static void equals_ref(T2&)
{
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2> static void convertible(T2)
{
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
}
};
};
}
#endif
+31 -32
View File
@@ -6,12 +6,11 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD)
#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <boost/core/lightweight_test.hpp>
namespace test {
struct object_count
{
struct object_count
{
int instances;
int constructions;
@@ -20,52 +19,52 @@ struct object_count
void construct()
{
++instances;
++constructions;
++instances;
++constructions;
}
void destruct()
{
if (instances == 0) {
BOOST_ERROR("Unbalanced constructions.");
} else {
--instances;
}
if (instances == 0) {
BOOST_ERROR("Unbalanced constructions.");
} else {
--instances;
}
}
bool operator==(object_count const& x) const
{
return instances == x.instances && constructions == x.constructions;
return instances == x.instances && constructions == x.constructions;
}
bool operator!=(object_count const& x) const { return !(*this == x); }
friend std::ostream& operator<<(std::ostream& out, object_count const& c)
{
out << "[instances: " << c.instances
<< ", constructions: " << c.constructions << "]";
return out;
out << "[instances: " << c.instances
<< ", constructions: " << c.constructions << "]";
return out;
}
};
};
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
object_count global_object_count;
}
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
object_count global_object_count;
}
struct counted_object
{
struct counted_object
{
counted_object() { global_object_count.construct(); }
counted_object(counted_object const&) { global_object_count.construct(); }
~counted_object() { global_object_count.destruct(); }
};
};
struct check_instances
{
struct check_instances
{
int instances_;
int constructions_;
@@ -76,15 +75,15 @@ struct check_instances
}
~check_instances()
{
BOOST_TEST(global_object_count.instances == instances_);
BOOST_TEST(global_object_count.instances == instances_);
}
int instances() const { return global_object_count.instances - instances_; }
int constructions() const
{
return global_object_count.constructions - constructions_;
return global_object_count.constructions - constructions_;
}
};
};
}
#endif
+40 -39
View File
@@ -10,59 +10,60 @@
#include "./list.hpp"
#include "./metafunctions.hpp"
#include <algorithm>
#include <boost/detail/lightweight_test.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
namespace test {
template <class T1, class T2>
bool equivalent_impl(T1 const& x, T2 const& y, base_type)
{
template <class T1, class T2>
bool equivalent_impl(T1 const& x, T2 const& y, base_type)
{
return x == y;
}
}
template <class T>
bool equivalent_impl(boost::hash<T> const&, boost::hash<T> const&, derived_type)
{
template <class T>
bool equivalent_impl(
boost::hash<T> const&, boost::hash<T> const&, derived_type)
{
return true;
}
}
template <class T>
bool equivalent_impl(
template <class T>
bool equivalent_impl(
std::equal_to<T> const&, std::equal_to<T> const&, derived_type)
{
{
return true;
}
}
template <class T1, class T2, class T3, class T4>
bool equivalent_impl(
template <class T1, class T2, class T3, class T4>
bool equivalent_impl(
std::pair<T1, T2> const& x1, std::pair<T3, T4> const& x2, derived_type)
{
{
return equivalent_impl(x1.first, x2.first, derived) &&
equivalent_impl(x1.second, x2.second, derived);
}
}
struct equivalent_type
{
struct equivalent_type
{
equivalent_type() {}
template <class T1, class T2>
bool operator()(T1 const& x, T2 const& y) const
{
return equivalent_impl(x, y, derived);
return equivalent_impl(x, y, derived);
}
};
};
const equivalent_type equivalent;
const equivalent_type equivalent;
template <class Container> class unordered_equivalence_tester
{
BOOST_DEDUCED_TYPENAME Container::size_type size_;
BOOST_DEDUCED_TYPENAME Container::hasher hasher_;
BOOST_DEDUCED_TYPENAME Container::key_equal key_equal_;
template <class Container> class unordered_equivalence_tester
{
typename Container::size_type size_;
typename Container::hasher hasher_;
typename Container::key_equal key_equal_;
float max_load_factor_;
typedef test::list<BOOST_DEDUCED_TYPENAME Container::value_type> value_list;
typedef test::list<typename Container::value_type> value_list;
value_list values_;
public:
@@ -70,26 +71,26 @@ template <class Container> class unordered_equivalence_tester
: size_(x.size()), hasher_(x.hash_function()), key_equal_(x.key_eq()),
max_load_factor_(x.max_load_factor()), values_(x.begin(), x.end())
{
values_.sort();
values_.sort();
}
bool operator()(Container const& x) const
{
if (!((size_ == x.size()) &&
(test::equivalent(hasher_, x.hash_function())) &&
(test::equivalent(key_equal_, x.key_eq())) &&
(max_load_factor_ == x.max_load_factor()) &&
(values_.size() == x.size())))
return false;
if (!((size_ == x.size()) &&
(test::equivalent(hasher_, x.hash_function())) &&
(test::equivalent(key_equal_, x.key_eq())) &&
(max_load_factor_ == x.max_load_factor()) &&
(values_.size() == x.size())))
return false;
value_list copy(x.begin(), x.end());
copy.sort();
return values_ == copy;
value_list copy(x.begin(), x.end());
copy.sort();
return values_ == copy;
}
private:
unordered_equivalence_tester();
};
};
}
#endif
+210 -133
View File
@@ -14,64 +14,59 @@
#include <boost/preprocessor/seq/for_each_product.hpp>
#define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \
{ \
test_func<type> fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
}
UNORDERED_AUTO_TEST (name) { \
test_func<type> fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
}
#define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
UNORDERED_AUTO_TEST(name) \
{ \
for (unsigned i = 0; i < n; ++i) { \
test_func<type> fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
} \
}
UNORDERED_AUTO_TEST (name) { \
for (unsigned i = 0; i < n; ++i) { \
test_func<type> fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
} \
}
#define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
#define EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
EXCEPTION_TESTS_OP, (test_seq)((1))(param_seq))
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((1))(param_seq))
#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq))
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq))
#define EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))), \
BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_ELEM(2, product))
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))), \
BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_ELEM(2, product))
#define UNORDERED_SCOPE(scope_name) \
for (::test::scope_guard unordered_test_guard( \
BOOST_STRINGIZE(scope_name)); \
!unordered_test_guard.dismissed(); unordered_test_guard.dismiss())
for (::test::scope_guard unordered_test_guard(BOOST_STRINGIZE(scope_name)); \
!unordered_test_guard.dismissed(); unordered_test_guard.dismiss())
#define UNORDERED_EPOINT(name) \
if (::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \
}
if (::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \
}
#define ENABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true)
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true)
#define DISABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false)
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false)
namespace test {
static char const* scope = "";
bool exceptions_enabled = false;
static char const* scope = "";
bool exceptions_enabled = false;
class scope_guard
{
class scope_guard
{
scope_guard& operator=(scope_guard const&);
scope_guard(scope_guard const&);
@@ -83,22 +78,22 @@ class scope_guard
scope_guard(char const* name)
: old_scope_(scope), scope_(name), dismissed_(false)
{
scope = scope_;
scope = scope_;
}
~scope_guard()
{
if (dismissed_)
scope = old_scope_;
if (dismissed_)
scope = old_scope_;
}
void dismiss() { dismissed_ = true; }
bool dismissed() const { return dismissed_; }
};
};
class exceptions_enable
{
class exceptions_enable
{
exceptions_enable& operator=(exceptions_enable const&);
exceptions_enable(exceptions_enable const&);
@@ -109,65 +104,65 @@ class exceptions_enable
exceptions_enable(bool enable)
: old_value_(exceptions_enabled), released_(false)
{
exceptions_enabled = enable;
exceptions_enabled = enable;
}
~exceptions_enable()
{
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
}
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
}
}
void release()
{
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
}
if (!released_) {
exceptions_enabled = old_value_;
released_ = true;
}
}
};
};
struct exception_base
{
struct exception_base
{
struct data_type
{
};
struct strong_type
{
template <class T> void store(T const&) {}
template <class T> void test(T const&) const {}
template <class T> void store(T const&) {}
template <class T> void test(T const&) const {}
};
data_type init() const { return data_type(); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
};
};
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)() const, T2 const& obj, P1&, P2&)
{
{
(obj.*fn)();
}
}
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)(P1&) const, T2 const& obj, P1& p1, P2&)
{
{
(obj.*fn)(p1);
}
}
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(
void (T::*fn)(P1&, P2&) const, T2 const& obj, P1& p1, P2& p2)
{
{
(obj.*fn)(p1, p2);
}
}
template <class T> T const& constant(T const& x) { return x; }
template <class T> T const& constant(T const& x) { return x; }
template <class Test> class test_runner
{
template <class Test> class test_runner
{
Test const& test_;
bool exception_in_check_;
@@ -178,94 +173,176 @@ template <class Test> class test_runner
test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
void run()
{
DISABLE_EXCEPTIONS;
test::check_instances check;
test::scope = "";
BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
BOOST_DEDUCED_TYPENAME Test::strong_type strong;
strong.store(x);
DISABLE_EXCEPTIONS;
test::check_instances check;
test::scope = "";
typename Test::data_type x(test_.init());
typename Test::strong_type strong;
strong.store(x);
try {
ENABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test, typename Test::data_type,
typename Test::strong_type>(&Test::run, test_, x, strong);
} catch (...) {
try {
ENABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test,
BOOST_DEDUCED_TYPENAME Test::data_type,
BOOST_DEDUCED_TYPENAME Test::strong_type>(
&Test::run, test_, x, strong);
DISABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test, typename Test::data_type const,
typename Test::strong_type const>(
&Test::check, test_, constant(x), constant(strong));
} catch (...) {
try {
DISABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test,
BOOST_DEDUCED_TYPENAME Test::data_type const,
BOOST_DEDUCED_TYPENAME Test::strong_type const>(
&Test::check, test_, constant(x), constant(strong));
} catch (...) {
exception_in_check_ = true;
}
throw;
exception_in_check_ = true;
}
throw;
}
}
void end()
{
if (exception_in_check_) {
BOOST_ERROR("Unexcpected exception in test_runner check call.");
}
if (exception_in_check_) {
BOOST_ERROR("Unexcpected exception in test_runner check call.");
}
}
};
};
// Quick exception testing based on lightweight test
// Quick exception testing based on lightweight test
namespace lightweight {
static int iteration;
static int count;
namespace lightweight {
static int iteration;
static int count;
struct test_exception
{
char const* name;
test_exception(char const* n) : name(n) {}
};
struct test_exception
{
char const* name;
test_exception(char const* n) : name(n) {}
};
struct test_failure
{
};
struct test_failure
{
};
void epoint(char const* name)
{
++count;
if (count == iteration) {
void epoint(char const* name)
{
++count;
if (count == iteration) {
throw test_exception(name);
}
}
}
template <class Test> void exception_safety(Test const& f, char const* /*name*/)
{
test_runner<Test> runner(f);
template <class Test>
void exception_safety(Test const& f, char const* /*name*/)
{
test_runner<Test> runner(f);
iteration = 0;
bool success = false;
char const* error_msg = 0;
do {
iteration = 0;
bool success = false;
unsigned int failure_count = 0;
char const* error_msg = 0;
do {
int error_count = boost::detail::test_errors();
++iteration;
count = 0;
try {
runner.run();
success = true;
runner.run();
success = true;
} catch (test_failure) {
error_msg = "test_failure caught.";
break;
} catch (test_exception) {
continue;
error_msg = "test_failure caught.";
break;
} catch (test_exception e) {
if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl;
}
} catch (...) {
error_msg = "Unexpected exception.";
break;
error_msg = "Unexpected exception.";
break;
}
} while (!success);
if (error_msg) {
if (error_count != boost::detail::test_errors()) {
++failure_count;
}
} while (!success && failure_count < 5);
if (error_msg) {
BOOST_ERROR(error_msg);
}
runner.end();
}
runner.end();
}
}
//
// An alternative way to run exception tests.
// See merge_exception_tests.cpp for an example.
struct exception_looper
{
bool success;
unsigned int failure_count;
char const* error_msg;
int error_count;
exception_looper() : success(false), failure_count(0), error_msg(0) {}
void start() { iteration = 0; }
bool loop_condition() const
{
return !error_msg && !success && failure_count < 5;
}
void start_iteration()
{
error_count = boost::detail::test_errors();
++iteration;
count = 0;
}
void successful_run() { success = true; }
void test_failure_caught(test_failure const&)
{
error_msg = "test_failure caught.";
}
void test_exception_caught(test_exception const& e)
{
if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl;
}
}
void unexpected_exception_caught()
{
error_msg = "Unexpected exception.";
}
void end()
{
if (error_msg) {
BOOST_ERROR(error_msg);
}
}
};
#define EXCEPTION_LOOP(op) \
test::lightweight::exception_looper looper; \
looper.start(); \
while (looper.loop_condition()) { \
looper.start_iteration(); \
try { \
op; \
looper.successful_run(); \
} catch (test::lightweight::test_failure e) { \
looper.test_failure_caught(e); \
} catch (test::lightweight::test_exception e) { \
looper.test_exception_caught(e); \
} catch (...) { \
looper.unexpected_exception_caught(); \
} \
} \
looper.end();
}
}
#endif
+13 -13
View File
@@ -9,24 +9,24 @@
#include <string>
namespace test {
typedef enum {
typedef enum {
default_generator,
generate_collisions,
limited_range
} random_generator;
} random_generator;
int generate(int const*, random_generator);
char generate(char const*, random_generator);
signed char generate(signed char const*, random_generator);
std::string generate(std::string const*, random_generator);
float generate(float const*, random_generator);
int generate(int const*, random_generator);
char generate(char const*, random_generator);
signed char generate(signed char const*, random_generator);
std::string generate(std::string const*, random_generator);
float generate(float const*, random_generator);
struct base_type
{
} base;
struct derived_type : base_type
{
} derived;
struct base_type
{
} base;
struct derived_type : base_type
{
} derived;
}
#endif
+33 -34
View File
@@ -19,45 +19,45 @@
#include <utility>
namespace test {
struct seed_t
{
struct seed_t
{
seed_t(unsigned int x)
{
using namespace std;
srand(x);
using namespace std;
srand(x);
}
};
};
std::size_t random_value(std::size_t max)
{
std::size_t random_value(std::size_t max)
{
using namespace std;
return static_cast<std::size_t>(rand()) % max;
}
}
inline int generate(int const*, random_generator g)
{
inline int generate(int const*, random_generator g)
{
using namespace std;
int value = rand();
if (g == limited_range) {
value = value % 100;
value = value % 100;
}
return value;
}
}
inline char generate(char const*, random_generator)
{
inline char generate(char const*, random_generator)
{
using namespace std;
return static_cast<char>((rand() >> 1) % (128 - 32) + 32);
}
}
inline signed char generate(signed char const*, random_generator)
{
inline signed char generate(signed char const*, random_generator)
{
using namespace std;
return static_cast<signed char>(rand());
}
}
inline std::string generate(std::string const*, random_generator g)
{
inline std::string generate(std::string const*, random_generator g)
{
using namespace std;
char* char_ptr = 0;
@@ -65,30 +65,29 @@ inline std::string generate(std::string const*, random_generator g)
std::string result;
if (g == limited_range) {
std::size_t length = test::random_value(2) + 2;
std::size_t length = test::random_value(2) + 2;
char const* strings[] = {"'vZh(3~ms", "%m", "_Y%U", "N'Y", "4,J_J"};
for (std::size_t i = 0; i < length; ++i) {
result +=
strings[random_value(sizeof(strings) / sizeof(strings[0]))];
}
char const* strings[] = {"'vZh(3~ms", "%m", "_Y%U", "N'Y", "4,J_J"};
for (std::size_t i = 0; i < length; ++i) {
result += strings[random_value(sizeof(strings) / sizeof(strings[0]))];
}
} else {
std::size_t length = test::random_value(10) + 1;
for (std::size_t i = 0; i < length; ++i) {
result += generate(char_ptr, g);
}
std::size_t length = test::random_value(10) + 1;
for (std::size_t i = 0; i < length; ++i) {
result += generate(char_ptr, g);
}
}
return result;
}
}
float generate(float const*, random_generator g)
{
float generate(float const*, random_generator g)
{
using namespace std;
int x = 0;
int value = generate(&x, g);
return (float)value / (float)RAND_MAX;
}
}
}
#endif
+26 -23
View File
@@ -6,48 +6,51 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_HEADER
#include <iterator>
namespace test {
template <class Container> struct get_key_impl
{
typedef BOOST_DEDUCED_TYPENAME Container::key_type key_type;
template <class Container> struct get_key_impl
{
typedef typename Container::key_type key_type;
static key_type const& get_key(key_type const& x) { return x; }
template <class T>
static key_type const& get_key(std::pair<key_type, T> const& x, char = 0)
{
return x.first;
return x.first;
}
template <class T>
static key_type const& get_key(
std::pair<key_type const, T> const& x, unsigned char = 0)
std::pair<key_type const, T> const& x, unsigned char = 0)
{
return x.first;
return x.first;
}
};
};
template <class Container, class T>
inline BOOST_DEDUCED_TYPENAME Container::key_type const& get_key(T const& x)
{
template <class Container, class T>
inline typename Container::key_type const& get_key(T const& x)
{
return get_key_impl<Container>::get_key(x);
}
}
// test::next
//
// Increments an iterator by 1 or a given value.
// Like boost::next, but simpler and slower.
// test::next
//
// Increments an iterator by 1 or a given value.
// Like boost::next, but simpler.
// Mainly because boost::next uses an MPL file
// which causes warnings.
template <typename Iterator> Iterator next(Iterator it) { return ++it; }
template <typename Iterator> Iterator next(Iterator it) { return ++it; }
template <typename Iterator, typename IntType>
Iterator next(Iterator it, IntType x)
{
for (; x > 0; --x) {
++it;
}
template <typename Iterator, typename IntType>
Iterator next(Iterator it, IntType x)
{
std::advance(it,
static_cast<typename std::iterator_traits<Iterator>::difference_type>(x));
return it;
}
}
}
#endif
+59 -67
View File
@@ -7,13 +7,12 @@
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
#include <boost/config.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <iterator>
namespace test {
template <class Iterator> struct proxy
{
typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type;
template <class Iterator> struct proxy
{
typedef typename Iterator::value_type value_type;
explicit proxy(value_type const& v) : v_(v) {}
proxy(proxy const& x) : v_(x.v_) {}
@@ -23,18 +22,15 @@ template <class Iterator> struct proxy
private:
proxy& operator=(proxy const&);
};
};
template <class Iterator>
struct input_iterator_adaptor
: public std::iterator<std::input_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator> >
{
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
template <class Iterator> struct input_iterator_adaptor
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef typename std::iterator_traits<Iterator>::pointer pointer;
typedef proxy<Iterator> reference;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
input_iterator_adaptor() : base_() {}
explicit input_iterator_adaptor(Iterator& it) : base_(&it) {}
@@ -42,43 +38,39 @@ struct input_iterator_adaptor
value_type* operator->() const { return &**base_; }
input_iterator_adaptor& operator++()
{
++*base_;
return *this;
++*base_;
return *this;
}
// input_iterator_adaptor operator++(int) {
//}
bool operator==(input_iterator_adaptor const& x) const
{
return *base_ == *x.base_;
return *base_ == *x.base_;
}
bool operator!=(input_iterator_adaptor const& x) const
{
return *base_ != *x.base_;
return *base_ != *x.base_;
}
private:
Iterator* base_;
};
};
template <class Iterator>
input_iterator_adaptor<Iterator> input_iterator(Iterator& it)
{
template <class Iterator>
input_iterator_adaptor<Iterator> input_iterator(Iterator& it)
{
return input_iterator_adaptor<Iterator>(it);
}
}
template <class Iterator>
struct copy_iterator_adaptor
: 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,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator> >
{
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type
difference_type;
template <class Iterator> struct copy_iterator_adaptor
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef
typename std::iterator_traits<Iterator>::difference_type difference_type;
typedef typename std::iterator_traits<Iterator>::iterator_category
iterator_category;
typedef typename std::iterator_traits<Iterator>::pointer pointer;
typedef proxy<Iterator> reference;
copy_iterator_adaptor() : base_() {}
explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {}
@@ -87,87 +79,87 @@ struct copy_iterator_adaptor
value_type operator[](difference_type d) { return base_[d]; }
copy_iterator_adaptor& operator++()
{
++base_;
return *this;
++base_;
return *this;
}
copy_iterator_adaptor operator++(int)
{
copy_iterator_adaptor tmp(*this);
++base_;
return tmp;
copy_iterator_adaptor tmp(*this);
++base_;
return tmp;
}
copy_iterator_adaptor& operator--()
{
--base_;
return *this;
--base_;
return *this;
}
copy_iterator_adaptor operator--(int)
{
copy_iterator_adaptor tmp(*this);
--base_;
return tmp;
copy_iterator_adaptor tmp(*this);
--base_;
return tmp;
}
copy_iterator_adaptor operator+=(difference_type x)
{
base_ += x;
return *this;
base_ += x;
return *this;
}
copy_iterator_adaptor operator-=(difference_type x)
{
base_ -= x;
return *this;
base_ -= x;
return *this;
}
copy_iterator_adaptor operator+(difference_type n)
{
return copy_iterator_adaptor(base_ + n);
return copy_iterator_adaptor(base_ + n);
}
copy_iterator_adaptor operator-(difference_type n)
{
return copy_iterator_adaptor(base_ - n);
return copy_iterator_adaptor(base_ - n);
}
friend copy_iterator_adaptor operator+(
difference_type n, copy_iterator_adaptor x)
difference_type n, copy_iterator_adaptor x)
{
return x + n;
return x + n;
}
difference_type operator-(copy_iterator_adaptor const& other)
{
return base_ - other.base_;
return base_ - other.base_;
}
bool operator==(copy_iterator_adaptor const& x) const
{
return base_ == x.base_;
return base_ == x.base_;
}
bool operator!=(copy_iterator_adaptor const& x) const
{
return base_ != x.base_;
return base_ != x.base_;
}
bool operator<(copy_iterator_adaptor const& x) const
{
return base_ < x.base_;
return base_ < x.base_;
}
bool operator>(copy_iterator_adaptor const& x) const
{
return base_ > x.base_;
return base_ > x.base_;
}
bool operator<=(copy_iterator_adaptor const& x) const
{
return base_ <= x.base_;
return base_ <= x.base_;
}
bool operator>=(copy_iterator_adaptor const& x) const
{
return base_ >= x.base_;
return base_ >= x.base_;
}
private:
Iterator base_;
};
};
template <class Iterator>
copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
{
template <class Iterator>
copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
{
return copy_iterator_adaptor<Iterator>(it);
}
}
}
#endif
+68 -63
View File
@@ -22,100 +22,105 @@
#endif
namespace test {
template <class X> void check_equivalent_keys(X const& x1)
{
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
template <class X> void check_equivalent_keys(X const& x1)
{
typename X::key_equal eq = x1.key_eq();
typedef typename X::key_type key_type;
std::set<key_type, std::less<key_type> > found_;
BOOST_DEDUCED_TYPENAME X::const_iterator it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
typename X::const_iterator it = x1.begin(), end = x1.end();
typename X::size_type size = 0;
while (it != end) {
// First test that the current key has not occurred before, required
// to test either that keys are unique or that equivalent keys are
// adjacent. (6.3.1/6)
key_type key = get_key<X>(*it);
if (!found_.insert(key).second)
BOOST_ERROR("Elements with equivalent keys aren't adjacent.");
// First test that the current key has not occurred before, required
// to test either that keys are unique or that equivalent keys are
// adjacent. (6.3.1/6)
key_type key = get_key<X>(*it);
if (!found_.insert(key).second)
BOOST_ERROR("Elements with equivalent keys aren't adjacent.");
// Iterate over equivalent keys, counting them.
unsigned int count = 0;
do {
++it;
++count;
++size;
} while (it != end && eq(get_key<X>(*it), key));
// Iterate over equivalent keys, counting them.
unsigned int count = 0;
do {
++it;
++count;
++size;
} while (it != end && eq(get_key<X>(*it), key));
// If the container has unique keys, test that there's only one.
// Since the previous test makes sure that all equivalent keys are
// adjacent, this is all the equivalent keys - so the test is
// sufficient. (6.3.1/6 again).
if (test::has_unique_keys<X>::value && count != 1)
BOOST_ERROR("Non-unique key.");
// If the container has unique keys, test that there's only one.
// Since the previous test makes sure that all equivalent keys are
// adjacent, this is all the equivalent keys - so the test is
// sufficient. (6.3.1/6 again).
if (test::has_unique_keys<X>::value && count != 1)
BOOST_ERROR("Non-unique key.");
if (x1.count(key) != count) {
BOOST_ERROR("Incorrect output of count.");
std::cerr << x1.count(key) << "," << count << "\n";
}
if (x1.count(key) != count) {
BOOST_ERROR("Incorrect output of count.");
std::cerr << x1.count(key) << "," << count << "\n";
}
// Check that the keys are in the correct bucket and are
// adjacent in the bucket.
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)
BOOST_ERROR("Unable to find element with a local_iterator");
// Check that the keys are in the correct bucket and are
// adjacent in the bucket.
typename X::size_type bucket = x1.bucket(key);
typename X::const_local_iterator lit = x1.begin(bucket),
lend = x1.end(bucket);
unsigned int count_checked = 0;
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
++count_checked;
}
if (lit == lend) {
BOOST_ERROR("Unable to find element with a local_iterator");
std::cerr << "Checked: " << count_checked << " elements" << std::endl;
} else {
unsigned int count2 = 0;
for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
++count2;
++count2;
if (count != count2)
BOOST_ERROR("Element count doesn't match local_iterator.");
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;
}
if (eq(get_key<X>(*lit), key)) {
BOOST_ERROR("Non-adjacent element with equivalent key "
"in bucket.");
break;
}
}
}
};
// Check that size matches up.
if (x1.size() != size) {
BOOST_ERROR("x1.size() doesn't match actual size.");
std::cout << x1.size() << "/" << size << std::endl;
BOOST_ERROR("x1.size() doesn't match actual size.");
std::cout << x1.size() << "/" << size << std::endl;
}
// Check the load factor.
float load_factor =
size == 0 ? 0 : static_cast<float>(size) /
static_cast<float>(x1.bucket_count());
float load_factor = size == 0 ? 0
: static_cast<float>(size) /
static_cast<float>(x1.bucket_count());
using namespace std;
if (fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
// Check that size in the buckets matches up.
BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0;
typename X::size_type bucket_size = 0;
for (BOOST_DEDUCED_TYPENAME X::size_type i = 0; i < x1.bucket_count();
++i) {
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
begin2 = x1.begin(i),
end2 = x1.end(i);
begin2 != end2; ++begin2) {
++bucket_size;
}
for (typename X::size_type i = 0; i < x1.bucket_count(); ++i) {
for (typename X::const_local_iterator begin2 = x1.begin(i),
end2 = x1.end(i);
begin2 != end2; ++begin2) {
++bucket_size;
}
}
if (x1.size() != bucket_size) {
BOOST_ERROR("x1.size() doesn't match bucket size.");
std::cout << x1.size() << "/" << bucket_size << std::endl;
BOOST_ERROR("x1.size() doesn't match bucket size.");
std::cout << x1.size() << "/" << bucket_size << std::endl;
}
}
}
}
#if defined(BOOST_MSVC)
+188 -181
View File
@@ -16,143 +16,151 @@
#include <iterator>
namespace test {
template <typename It1, typename It2>
bool equal(It1 begin, It1 end, It2 compare)
{
template <typename It1, typename It2>
bool equal(It1 begin, It1 end, It2 compare)
{
for (; begin != end; ++begin, ++compare)
if (*begin != *compare)
return false;
if (*begin != *compare)
return false;
return true;
}
}
template <typename It1, typename It2, typename Pred>
bool equal(It1 begin, It1 end, It2 compare, Pred predicate)
{
template <typename It1, typename It2, typename Pred>
bool equal(It1 begin, It1 end, It2 compare, Pred predicate)
{
for (; begin != end; ++begin, ++compare)
if (!predicate(*begin, *compare))
return false;
if (!predicate(*begin, *compare))
return false;
return true;
}
}
template <typename T> class list;
template <typename T> class list;
namespace test_detail {
template <typename T> class list_node;
template <typename T> class list_data;
template <typename T> class list_iterator;
template <typename T> class list_const_iterator;
namespace test_detail {
template <typename T> class list_node;
template <typename T> class list_data;
template <typename T> class list_iterator;
template <typename T> class list_const_iterator;
template <typename T> class list_node
{
list_node(list_node const&);
list_node& operator=(list_node const&);
public:
T value_;
list_node* next_;
list_node(T const& v) : value_(v), next_(0) {}
list_node(T const& v, list_node* n) : value_(v), next_(n) {}
};
template <typename T> class list_data
{
public:
typedef list_node<T> node;
typedef unsigned int size_type;
node* first_;
node** last_ptr_;
size_type size_;
list_data() : first_(0), last_ptr_(&first_), size_(0) {}
~list_data()
template <typename T> class list_node
{
list_node(list_node const&);
list_node& operator=(list_node const&);
public:
T value_;
list_node* next_;
list_node(T const& v) : value_(v), next_(0) {}
list_node(T const& v, list_node* n) : value_(v), next_(n) {}
};
template <typename T> class list_data
{
public:
typedef list_node<T> node;
typedef unsigned int size_type;
node* first_;
node** last_ptr_;
size_type size_;
list_data() : first_(0), last_ptr_(&first_), size_(0) {}
~list_data()
{
while (first_) {
node* tmp = first_;
first_ = first_->next_;
delete tmp;
node* tmp = first_;
first_ = first_->next_;
delete tmp;
}
}
}
private:
list_data(list_data const&);
list_data& operator=(list_data const&);
};
private:
list_data(list_data const&);
list_data& operator=(list_data const&);
};
template <typename T>
class list_iterator
: public std::iterator<std::forward_iterator_tag, T, int, T*, T&>
{
friend class list_const_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_iterator() : ptr_(0) {}
explicit list_iterator(node* x) : ptr_(x) {}
T& operator*() const { return ptr_->value_; }
T* operator->() const { return &ptr_->value_; }
list_iterator& operator++()
template <typename T> class list_iterator
{
friend class list_const_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
list_iterator() : ptr_(0) {}
explicit list_iterator(node* x) : ptr_(x) {}
T& operator*() const { return ptr_->value_; }
T* operator->() const { return &ptr_->value_; }
list_iterator& operator++()
{
ptr_ = ptr_->next_;
return *this;
}
list_iterator operator++(int)
{
}
list_iterator operator++(int)
{
list_iterator tmp = *this;
ptr_ = ptr_->next_;
return tmp;
}
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
};
}
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
};
template <typename T>
class list_const_iterator : public std::iterator<std::forward_iterator_tag, T,
int, T const*, T const&>
{
friend class list_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_iterator<T> iterator;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_const_iterator() : ptr_(0) {}
list_const_iterator(list_iterator<T> const& x) : ptr_(x.ptr_) {}
T const& operator*() const { return ptr_->value_; }
T const* operator->() const { return &ptr_->value_; }
list_const_iterator& operator++()
template <typename T> class list_const_iterator
{
friend class list_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_iterator<T> iterator;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
typedef T value_type;
typedef T const* pointer;
typedef T const& reference;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
list_const_iterator() : ptr_(0) {}
list_const_iterator(list_iterator<T> const& x) : ptr_(x.ptr_) {}
T const& operator*() const { return ptr_->value_; }
T const* operator->() const { return &ptr_->value_; }
list_const_iterator& operator++()
{
ptr_ = ptr_->next_;
return *this;
}
}
list_const_iterator operator++(int)
{
list_const_iterator operator++(int)
{
list_const_iterator tmp = *this;
ptr_ = ptr_->next_;
return tmp;
}
}
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
};
}
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
};
}
template <typename T> class list
{
template <typename T> class list
{
typedef test::test_detail::list_data<T> data;
typedef test::test_detail::list_node<T> node;
data data_;
@@ -173,14 +181,14 @@ template <typename T> class list
template <class InputIterator>
list(InputIterator i, InputIterator j) : data_()
{
insert(i, j);
insert(i, j);
}
list& operator=(list const& other)
{
clear();
insert(other.begin(), other.end());
return *this;
clear();
insert(other.begin(), other.end());
return *this;
}
iterator begin() { return iterator(data_.first_); }
@@ -192,53 +200,53 @@ template <typename T> class list
template <class InputIterator> void insert(InputIterator i, InputIterator j)
{
for (; i != j; ++i)
push_back(*i);
for (; i != j; ++i)
push_back(*i);
}
void push_front(value_type const& v)
{
data_.first_ = new node(v, data_.first_);
if (!data_.size_)
data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_;
data_.first_ = new node(v, data_.first_);
if (!data_.size_)
data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_;
}
void push_back(value_type const& v)
{
*data_.last_ptr_ = new node(v);
data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_;
*data_.last_ptr_ = new node(v);
data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_;
}
void clear()
{
while (data_.first_) {
node* tmp = data_.first_;
data_.first_ = data_.first_->next_;
--data_.size_;
delete tmp;
}
data_.last_ptr_ = &data_.first_;
while (data_.first_) {
node* tmp = data_.first_;
data_.first_ = data_.first_->next_;
--data_.size_;
delete tmp;
}
data_.last_ptr_ = &data_.first_;
}
void erase(const_iterator i, const_iterator j)
{
node** ptr = &data_.first_;
node** ptr = &data_.first_;
while (*ptr != i.ptr_) {
ptr = &(*ptr)->next_;
}
while (*ptr != i.ptr_) {
ptr = &(*ptr)->next_;
}
while (*ptr != j.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
delete to_delete;
}
while (*ptr != j.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
delete to_delete;
}
if (!*ptr)
data_.last_ptr_ = ptr;
if (!*ptr)
data_.last_ptr_ = ptr;
}
bool empty() const { return !data_.size_; }
@@ -249,14 +257,14 @@ template <typename T> class list
template <typename Less> void sort(Less less = Less())
{
if (!empty())
merge_sort(
&data_.first_, (std::numeric_limits<size_type>::max)(), less);
if (!empty())
merge_sort(
&data_.first_, (std::numeric_limits<size_type>::max)(), less);
}
bool operator==(list const& y) const
{
return size() == y.size() && test::equal(begin(), end(), y.begin());
return size() == y.size() && test::equal(begin(), end(), y.begin());
}
bool operator!=(list const& y) const { return !(*this == y); }
@@ -265,56 +273,55 @@ template <typename T> class list
template <typename Less>
node** merge_sort(node** l, size_type recurse_limit, Less less)
{
node** ptr = &(*l)->next_;
for (size_type count = 0; count < recurse_limit && *ptr; ++count) {
ptr = merge_adjacent_ranges(
l, ptr, merge_sort(ptr, count, less), less);
}
return ptr;
node** ptr = &(*l)->next_;
for (size_type count = 0; count < recurse_limit && *ptr; ++count) {
ptr = merge_adjacent_ranges(l, ptr, merge_sort(ptr, count, less), less);
}
return ptr;
}
template <typename Less>
node** merge_adjacent_ranges(
node** first, node** second, node** third, Less less)
node** first, node** second, node** third, Less less)
{
for (;;) {
for (;;) {
for (;;) {
if (first == second)
return third;
if (less((*second)->value_, (*first)->value_))
break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, second, third);
first = &(*first)->next_;
// Since the two ranges we just swapped, the order is now:
// first...third...second
for (;;) {
if (first == third)
return second;
if (!less((*first)->value_, (*third)->value_))
break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, third, second);
first = &(*first)->next_;
if (first == second)
return third;
if (less((*second)->value_, (*first)->value_))
break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, second, third);
first = &(*first)->next_;
// Since the two ranges we just swapped, the order is now:
// first...third...second
for (;;) {
if (first == third)
return second;
if (!less((*first)->value_, (*third)->value_))
break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, third, second);
first = &(*first)->next_;
}
}
void swap_adjacent_ranges(node** first, node** second, node** third)
{
node* tmp = *first;
*first = *second;
*second = *third;
*third = tmp;
if (!*second)
data_.last_ptr_ = second;
node* tmp = *first;
*first = *second;
*second = *third;
*third = tmp;
if (!*second)
data_.last_ptr_ = second;
}
};
};
}
#endif
+140 -109
View File
@@ -13,146 +13,177 @@
#include <memory>
namespace test {
namespace detail {
struct memory_area
{
void const* start;
void const* end;
memory_area(void const* s, void const* e) : start(s), end(e)
namespace detail {
struct memory_area
{
void const* start;
void const* end;
memory_area(void const* s, void const* e) : start(s), end(e)
{
BOOST_ASSERT(start != end);
}
};
}
};
struct memory_track
{
explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {}
int constructed_;
int tag_;
};
// This is a bit dodgy as it defines overlapping
// areas as 'equal', so this isn't a total ordering.
// But it is for non-overlapping memory regions - which
// is what'll be stored.
//
// All searches will be for areas entirely contained by
// a member of the set - so it should find the area that contains
// the region that is searched for.
struct memory_area_compare
{
bool operator()(memory_area const& x, memory_area const& y) const
struct memory_track
{
return x.end <= y.start;
}
};
explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {}
struct memory_tracker
{
typedef std::map<memory_area, memory_track, memory_area_compare,
int constructed_;
int tag_;
};
// This is a bit dodgy as it defines overlapping
// areas as 'equal', so this isn't a total ordering.
// But it is for non-overlapping memory regions - which
// is what'll be stored.
//
// All searches will be for areas entirely contained by
// a member of the set - so it should find the area that contains
// the region that is searched for.
struct memory_area_compare
{
bool operator()(memory_area const& x, memory_area const& y) const
{
return x.end <= y.start;
}
};
struct memory_tracker
{
typedef std::map<memory_area, memory_track, memory_area_compare,
std::allocator<std::pair<memory_area const, memory_track> > >
allocated_memory_type;
allocated_memory_type allocated_memory;
unsigned int count_allocators;
unsigned int count_allocations;
unsigned int count_constructions;
allocated_memory_type allocated_memory;
unsigned int count_allocators;
unsigned int count_allocations;
unsigned int count_constructions;
bool tracking_constructions;
memory_tracker()
: count_allocators(0), count_allocations(0), count_constructions(0)
{
}
memory_tracker()
: count_allocators(0), count_allocations(0), count_constructions(0),
tracking_constructions(true)
{
}
void allocator_ref()
{
~memory_tracker() { BOOST_TEST(count_allocators == 0); }
void allocator_ref()
{
if (count_allocators == 0) {
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
}
++count_allocators;
}
void allocator_unref()
{
BOOST_TEST(count_allocators > 0);
if (count_allocators > 0) {
--count_allocators;
if (count_allocators == 0) {
bool no_allocations_left = (count_allocations == 0);
bool no_constructions_left = (count_constructions == 0);
bool allocated_memory_empty = allocated_memory.empty();
// Clearing the data before the checks terminate the
// tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
BOOST_TEST(no_allocations_left);
BOOST_TEST(no_constructions_left);
BOOST_TEST(allocated_memory_empty);
}
}
++count_allocators;
}
}
void allocator_unref()
{
BOOST_TEST(count_allocators > 0);
if (count_allocators > 0) {
--count_allocators;
if (count_allocators == 0) {
bool no_allocations_left = (count_allocations == 0);
bool no_constructions_left = (count_constructions == 0);
bool allocated_memory_empty = allocated_memory.empty();
// Clearing the data before the checks terminate the
// tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
BOOST_TEST(no_allocations_left);
BOOST_TEST(no_constructions_left);
BOOST_TEST(allocated_memory_empty);
}
}
}
void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag)
{
void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag)
{
if (n == 0) {
BOOST_ERROR("Allocating 0 length array.");
BOOST_ERROR("Allocating 0 length array.");
} else {
++count_allocations;
allocated_memory.insert(std::pair<memory_area const, memory_track>(
memory_area(ptr, (char*)ptr + n * size), memory_track(tag)));
++count_allocations;
allocated_memory.insert(std::pair<memory_area const, memory_track>(
memory_area(ptr, (char*)ptr + n * size), memory_track(tag)));
}
}
}
void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag,
void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag,
bool check_tag_ = true)
{
{
allocated_memory_type::iterator pos =
allocated_memory.find(memory_area(ptr, (char*)ptr + n * size));
allocated_memory.find(memory_area(ptr, (char*)ptr + n * size));
if (pos == allocated_memory.end()) {
BOOST_ERROR("Deallocating unknown pointer.");
BOOST_ERROR("Deallocating unknown pointer.");
} else {
BOOST_TEST(pos->first.start == ptr);
BOOST_TEST(pos->first.end == (char*)ptr + n * size);
if (check_tag_)
BOOST_TEST(pos->second.tag_ == tag);
allocated_memory.erase(pos);
BOOST_TEST(pos->first.start == ptr);
BOOST_TEST(pos->first.end == (char*)ptr + n * size);
if (check_tag_)
BOOST_TEST(pos->second.tag_ == tag);
allocated_memory.erase(pos);
}
BOOST_TEST(count_allocations > 0);
if (count_allocations > 0)
--count_allocations;
}
--count_allocations;
}
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
++count_constructions;
}
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
if (tracking_constructions) {
++count_constructions;
}
}
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
BOOST_TEST(count_constructions > 0);
if (count_constructions > 0)
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
if (tracking_constructions) {
BOOST_TEST(count_constructions > 0);
if (count_constructions > 0)
--count_constructions;
}
};
}
}
}
};
}
namespace detail {
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually required by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker tracker;
}
}
namespace detail {
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually required by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker tracker;
}
}
namespace detail {
struct disable_construction_tracking
{
bool old_value;
disable_construction_tracking()
: old_value(detail::tracker.tracking_constructions)
{
test::detail::tracker.tracking_constructions = false;
}
~disable_construction_tracking()
{
test::detail::tracker.tracking_constructions = old_value;
}
private:
disable_construction_tracking(disable_construction_tracking const&);
disable_construction_tracking& operator=(
disable_construction_tracking const&);
};
}
}
#endif
+13 -17
View File
@@ -10,25 +10,21 @@
#include <boost/type_traits/is_same.hpp>
namespace test {
template <class Container>
struct is_set
: public boost::is_same<BOOST_DEDUCED_TYPENAME Container::key_type,
BOOST_DEDUCED_TYPENAME Container::value_type>
{
};
template <class Container>
struct is_set : public boost::is_same<typename Container::key_type,
typename Container::value_type>
{
};
template <class Container> struct has_unique_keys
{
static char flip(BOOST_DEDUCED_TYPENAME Container::iterator const&);
static long flip(
std::pair<BOOST_DEDUCED_TYPENAME Container::iterator, bool> const&);
template <class Container> struct has_unique_keys
{
static char flip(typename Container::iterator const&);
static long flip(std::pair<typename Container::iterator, bool> const&);
BOOST_STATIC_CONSTANT(bool,
value = sizeof(long) ==
sizeof(flip(
((Container*)0)
->insert(*(
BOOST_DEDUCED_TYPENAME Container::value_type*)0))));
};
value = sizeof(long) ==
sizeof(flip(
((Container*)0)->insert(*(typename Container::value_type*)0))));
};
}
#endif
+48 -48
View File
@@ -13,9 +13,9 @@
#include <boost/detail/select_type.hpp>
namespace test {
template <class X> struct unordered_generator_set
{
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
template <class X> struct unordered_generator_set
{
typedef typename X::value_type value_type;
random_generator type_;
@@ -23,26 +23,26 @@ template <class X> struct unordered_generator_set
template <class T> void fill(T& x, std::size_t len)
{
value_type* value_ptr = 0;
len += x.size();
value_type* value_ptr = 0;
len += x.size();
for (std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr, type_);
for (std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr, type_);
std::size_t count =
type_ == generate_collisions ? random_value(5) + 1 : 1;
std::size_t count =
type_ == generate_collisions ? random_value(5) + 1 : 1;
for (std::size_t j = 0; j < count; ++j) {
x.push_back(value);
}
for (std::size_t j = 0; j < count; ++j) {
x.push_back(value);
}
}
}
};
};
template <class X> struct unordered_generator_map
{
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type;
template <class X> struct unordered_generator_map
{
typedef typename X::key_type key_type;
typedef typename X::mapped_type mapped_type;
random_generator type_;
@@ -50,60 +50,60 @@ template <class X> struct unordered_generator_map
template <class T> void fill(T& x, std::size_t len)
{
key_type* key_ptr = 0;
mapped_type* mapped_ptr = 0;
key_type* key_ptr = 0;
mapped_type* mapped_ptr = 0;
for (std::size_t i = 0; i < len; ++i) {
key_type key = generate(key_ptr, type_);
for (std::size_t i = 0; i < len; ++i) {
key_type key = generate(key_ptr, type_);
std::size_t count =
type_ == generate_collisions ? random_value(5) + 1 : 1;
std::size_t count =
type_ == generate_collisions ? random_value(5) + 1 : 1;
for (std::size_t j = 0; j < count; ++j) {
x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr, type_)));
}
for (std::size_t j = 0; j < count; ++j) {
x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr, type_)));
}
}
}
};
};
template <class X>
struct unordered_generator_base
template <class X>
struct unordered_generator_base
: public boost::detail::if_true<test::is_set<X>::value>::
BOOST_NESTED_TEMPLATE then<test::unordered_generator_set<X>,
test::unordered_generator_map<X> >
{
};
BOOST_NESTED_TEMPLATE then<test::unordered_generator_set<X>,
test::unordered_generator_map<X> >
{
};
template <class X>
struct unordered_generator : public unordered_generator_base<X>::type
{
typedef BOOST_DEDUCED_TYPENAME unordered_generator_base<X>::type base;
template <class X>
struct unordered_generator : public unordered_generator_base<X>::type
{
typedef typename unordered_generator_base<X>::type base;
unordered_generator(random_generator const& type = default_generator)
: base(type)
{
}
};
};
template <class X>
struct random_values : public test::list<BOOST_DEDUCED_TYPENAME X::value_type>
{
template <class X>
struct random_values : public test::list<typename X::value_type>
{
random_values() {}
explicit random_values(std::size_t count,
test::random_generator const& generator = test::default_generator)
test::random_generator const& generator = test::default_generator)
{
fill(count, generator);
fill(count, generator);
}
void fill(std::size_t count,
test::random_generator const& generator = test::default_generator)
test::random_generator const& generator = test::default_generator)
{
test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
}
};
};
}
#endif
+13 -14
View File
@@ -13,31 +13,30 @@
#include <iterator>
namespace test {
template <class X> class strong
{
typedef test::list<BOOST_DEDUCED_TYPENAME X::value_type> values_type;
template <class X> class strong
{
typedef test::list<typename X::value_type> values_type;
values_type values_;
unsigned int allocations_;
public:
void store(X const& x, unsigned int allocations = 0)
{
DISABLE_EXCEPTIONS;
values_.clear();
values_.insert(x.cbegin(), x.cend());
allocations_ = allocations;
DISABLE_EXCEPTIONS;
values_.clear();
values_.insert(x.cbegin(), x.cend());
allocations_ = allocations;
}
void test(X const& x, unsigned int allocations = 0) const
{
if (!(x.size() == values_.size() &&
test::equal(
x.cbegin(), x.cend(), values_.begin(), test::equivalent)))
BOOST_ERROR("Strong exception safety failure.");
if (allocations != allocations_)
BOOST_ERROR("Strong exception failure: extra allocations.");
if (!(x.size() == values_.size() && test::equal(x.cbegin(), x.cend(),
values_.begin(), test::equivalent)))
BOOST_ERROR("Strong exception safety failure.");
if (allocations != allocations_)
BOOST_ERROR("Strong exception failure: extra allocations.");
}
};
};
}
#endif
+147 -71
View File
@@ -6,92 +6,143 @@
#if !defined(BOOST_UNORDERED_TEST_TEST_HEADER)
#define BOOST_UNORDERED_TEST_TEST_HEADER
#include <boost/detail/lightweight_test.hpp>
#include <boost/core/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 \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
{ \
BOOST_PP_CAT(x, _type) \
() : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
{ \
BOOST_PP_CAT(x, _type) \
() : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
{ \
::test::test_list::add_test(this); \
} \
void run(); \
}; \
BOOST_PP_CAT(x, _type) x; \
void BOOST_PP_CAT(x, _type)::run()
::test::get_state().add_test(this); \
} \
void run(); \
}; \
BOOST_PP_CAT(x, _type) x; \
void BOOST_PP_CAT(x, _type)::run()
#define RUN_TESTS() \
int main(int, char**) \
{ \
::test::write_compiler_info(); \
::test::test_list::run_tests(); \
return boost::report_errors(); \
}
int main(int, char**) \
{ \
BOOST_UNORDERED_TEST_COMPILER_INFO() \
::test::get_state().run_tests(); \
return boost::report_errors(); \
}
#define RUN_TESTS_QUIET() \
int main(int, char**) \
{ \
BOOST_UNORDERED_TEST_COMPILER_INFO() \
::test::get_state().run_tests(true); \
return boost::report_errors(); \
}
#define UNORDERED_SUB_TEST(x) \
for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \
UNORDERED_SUB_TEST_VALUE; \
UNORDERED_SUB_TEST_VALUE = \
::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE))
namespace test {
struct registered_test_base
{
struct registered_test_base
{
registered_test_base* next;
char const* name;
explicit registered_test_base(char const* n) : name(n) {}
virtual void run() = 0;
virtual ~registered_test_base() {}
};
};
namespace test_list {
static inline registered_test_base*& first()
{
static registered_test_base* ptr = 0;
return ptr;
}
struct state
{
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;
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();
std::cerr << std::flush;
std::cout << std::flush;
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>
@@ -101,25 +152,50 @@ inline void write_compiler_info()
// Run test with every combination of the parameters (a sequence of sequences)
#define UNORDERED_TEST(name, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((1))parameters)
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((1))parameters)
#define UNORDERED_TEST_REPEAT(name, n, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((n))parameters)
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((n))parameters)
#define UNORDERED_TEST_OP(r, product) \
UNORDERED_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
UNORDERED_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
#define UNORDERED_TEST_OP2(name, n, params) \
UNORDERED_AUTO_TEST( \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) \
{ \
for (int i = 0; i < n; ++i) \
name BOOST_PP_SEQ_TO_TUPLE(params); \
}
UNORDERED_AUTO_TEST ( \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) { \
for (int i = 0; i < n; ++i) \
name BOOST_PP_SEQ_TO_TUPLE(params); \
}
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
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
+67 -76
View File
@@ -20,84 +20,78 @@
#include <set>
namespace test {
template <typename X> struct equals_to_compare
{
typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> type;
};
template <typename X> struct equals_to_compare
{
typedef std::less<typename X::first_argument_type> type;
};
template <> struct equals_to_compare<test::equal_to>
{
template <> struct equals_to_compare<test::equal_to>
{
typedef test::less type;
};
};
template <class X1, class X2> void compare_range(X1 const& x1, X2 const& x2)
{
typedef test::list<BOOST_DEDUCED_TYPENAME X1::value_type> value_list;
template <class X1, class X2> void compare_range(X1 const& x1, X2 const& x2)
{
typedef test::list<typename X1::value_type> value_list;
value_list values1(x1.begin(), x1.end());
value_list values2(x2.begin(), x2.end());
values1.sort();
values2.sort();
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent));
}
test::equivalent));
}
template <class X1, class X2, class T>
void compare_pairs(X1 const& x1, X2 const& x2, T*)
{
template <class X1, class X2, class T>
void compare_pairs(X1 const& x1, X2 const& x2, T*)
{
test::list<T> values1(x1.first, x1.second);
test::list<T> values2(x2.first, x2.second);
values1.sort();
values2.sort();
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent));
}
test::equivalent));
}
template <typename X, bool is_set = test::is_set<X>::value,
template <typename X, bool is_set = test::is_set<X>::value,
bool has_unique_keys = test::has_unique_keys<X>::value>
struct ordered_base;
struct ordered_base;
template <typename X> struct ordered_base<X, true, true>
{
typedef std::set<BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, true, true>
{
typedef std::set<typename X::value_type,
typename equals_to_compare<typename X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, true, false>
{
typedef std::multiset<BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, true, false>
{
typedef std::multiset<typename X::value_type,
typename equals_to_compare<typename X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, false, true>
{
typedef std::map<BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, false, true>
{
typedef std::map<typename X::key_type, typename X::mapped_type,
typename equals_to_compare<typename X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, false, false>
{
typedef std::multimap<BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type;
};
template <typename X> struct ordered_base<X, false, false>
{
typedef std::multimap<typename X::key_type, typename X::mapped_type,
typename equals_to_compare<typename X::key_equal>::type>
type;
};
template <class X> class ordered : public ordered_base<X>::type
{
typedef BOOST_DEDUCED_TYPENAME ordered_base<X>::type base;
template <class X> class ordered : public ordered_base<X>::type
{
typedef typename ordered_base<X>::type base;
public:
typedef BOOST_DEDUCED_TYPENAME base::key_compare key_compare;
typedef typename base::key_compare key_compare;
ordered() : base() {}
@@ -105,43 +99,40 @@ template <class X> class ordered : public ordered_base<X>::type
void compare(X const& x) { compare_range(x, *this); }
void compare_key(
X const& x, BOOST_DEDUCED_TYPENAME X::value_type const& val)
void compare_key(X const& x, typename X::value_type const& val)
{
compare_pairs(x.equal_range(get_key<X>(val)),
this->equal_range(get_key<X>(val)),
(BOOST_DEDUCED_TYPENAME X::value_type*)0);
compare_pairs(x.equal_range(get_key<X>(val)),
this->equal_range(get_key<X>(val)), (typename X::value_type*)0);
}
template <class It> void insert_range(It b, It e)
{
while (b != e) {
this->insert(*b);
++b;
}
while (b != e) {
this->insert(*b);
++b;
}
}
};
};
template <class Equals>
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type create_compare(
Equals const&)
{
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type x;
template <class Equals>
typename equals_to_compare<Equals>::type create_compare(Equals const&)
{
typename equals_to_compare<Equals>::type x;
return x;
}
}
template <class X> ordered<X> create_ordered(X const& container)
{
template <class X> ordered<X> create_ordered(X const& container)
{
return ordered<X>(create_compare(container.key_eq()));
}
}
template <class X1, class X2>
void check_container(X1 const& container, X2 const& values)
{
template <class X1, class X2>
void check_container(X1 const& container, X2 const& values)
{
ordered<X1> tracker = create_ordered(container);
tracker.insert_range(values.begin(), values.end());
tracker.compare(container);
}
}
}
#endif
+133 -133
View File
@@ -14,141 +14,141 @@
#include "../helpers/memory.hpp"
namespace test {
struct allocator_false
{
struct allocator_false
{
enum
{
is_select_on_copy = 0,
is_propagate_on_swap = 0,
is_propagate_on_assign = 0,
is_propagate_on_move = 0,
cxx11_construct = 0
is_select_on_copy = 0,
is_propagate_on_swap = 0,
is_propagate_on_assign = 0,
is_propagate_on_move = 0,
cxx11_construct = 0
};
};
};
struct allocator_flags_all
{
struct allocator_flags_all
{
enum
{
is_select_on_copy = 1,
is_propagate_on_swap = 1,
is_propagate_on_assign = 1,
is_propagate_on_move = 1,
cxx11_construct = 1
is_select_on_copy = 1,
is_propagate_on_swap = 1,
is_propagate_on_assign = 1,
is_propagate_on_move = 1,
cxx11_construct = 1
};
};
};
struct select_copy : allocator_false
{
struct select_copy : allocator_false
{
enum
{
is_select_on_copy = 1
is_select_on_copy = 1
};
};
struct propagate_swap : allocator_false
{
};
struct propagate_swap : allocator_false
{
enum
{
is_propagate_on_swap = 1
is_propagate_on_swap = 1
};
};
struct propagate_assign : allocator_false
{
};
struct propagate_assign : allocator_false
{
enum
{
is_propagate_on_assign = 1
is_propagate_on_assign = 1
};
};
struct propagate_move : allocator_false
{
};
struct propagate_move : allocator_false
{
enum
{
is_propagate_on_move = 1
is_propagate_on_move = 1
};
};
};
struct no_select_copy : allocator_flags_all
{
struct no_select_copy : allocator_flags_all
{
enum
{
is_select_on_copy = 0
is_select_on_copy = 0
};
};
struct no_propagate_swap : allocator_flags_all
{
};
struct no_propagate_swap : allocator_flags_all
{
enum
{
is_propagate_on_swap = 0
is_propagate_on_swap = 0
};
};
struct no_propagate_assign : allocator_flags_all
{
};
struct no_propagate_assign : allocator_flags_all
{
enum
{
is_propagate_on_assign = 0
is_propagate_on_assign = 0
};
};
struct no_propagate_move : allocator_flags_all
{
};
struct no_propagate_move : allocator_flags_all
{
enum
{
is_propagate_on_move = 0
is_propagate_on_move = 0
};
};
};
template <typename Flag> struct swap_allocator_base
{
template <typename Flag> struct swap_allocator_base
{
struct propagate_on_container_swap
{
enum
{
value = Flag::is_propagate_on_swap
};
enum
{
value = Flag::is_propagate_on_swap
};
};
};
};
template <typename Flag> struct assign_allocator_base
{
template <typename Flag> struct assign_allocator_base
{
struct propagate_on_container_copy_assignment
{
enum
{
value = Flag::is_propagate_on_assign
};
enum
{
value = Flag::is_propagate_on_assign
};
};
};
};
template <typename Flag> struct move_allocator_base
{
template <typename Flag> struct move_allocator_base
{
struct propagate_on_container_move_assignment
{
enum
{
value = Flag::is_propagate_on_move
};
enum
{
value = Flag::is_propagate_on_move
};
};
};
};
namespace {
// boostinspect:nounnamed
bool force_equal_allocator_value = false;
}
namespace {
// boostinspect:nounnamed
bool force_equal_allocator_value = false;
}
struct force_equal_allocator
{
struct force_equal_allocator
{
bool old_value_;
explicit force_equal_allocator(bool value)
: old_value_(force_equal_allocator_value)
{
force_equal_allocator_value = value;
force_equal_allocator_value = value;
}
~force_equal_allocator() { force_equal_allocator_value = old_value_; }
};
};
template <typename T> struct cxx11_allocator_base
{
template <typename T> struct cxx11_allocator_base
{
int tag_;
int selected_;
@@ -162,20 +162,20 @@ template <typename T> struct cxx11_allocator_base
explicit cxx11_allocator_base(int t) : tag_(t), selected_(0)
{
detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
template <typename Y>
cxx11_allocator_base(cxx11_allocator_base<Y> const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
cxx11_allocator_base(cxx11_allocator_base const& x)
: tag_(x.tag_), selected_(x.selected_)
{
detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
~cxx11_allocator_base() { detail::tracker.allocator_unref(); }
@@ -186,71 +186,71 @@ template <typename T> struct cxx11_allocator_base
pointer allocate(size_type n)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
pointer allocate(size_type n, void const*)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(pointer p, size_type n)
{
// Only checking tags when propagating swap.
// Note that tags will be tested
// properly in the normal allocator.
detail::tracker.track_deallocate(
(void*)p, n, sizeof(T), tag_, !force_equal_allocator_value);
::operator delete((void*)p);
// Only checking tags when propagating swap.
// Note that tags will be tested
// properly in the normal allocator.
detail::tracker.track_deallocate(
(void*)p, n, sizeof(T), tag_, !force_equal_allocator_value);
::operator delete((void*)p);
}
void construct(T* p, T const& t)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t);
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename... Args>
void construct(T* p, BOOST_FWD_REF(Args)... args)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...);
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...);
}
#endif
void destroy(T* p)
{
detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T();
detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const
{
return (std::numeric_limits<size_type>::max)();
return (std::numeric_limits<size_type>::max)();
}
};
};
template <typename T, typename Flags = propagate_swap, typename Enable = void>
struct cxx11_allocator;
template <typename T, typename Flags = propagate_swap, typename Enable = void>
struct cxx11_allocator;
template <typename T, typename Flags>
struct cxx11_allocator<T, Flags,
template <typename T, typename Flags>
struct cxx11_allocator<T, Flags,
typename boost::disable_if_c<Flags::is_select_on_copy>::type>
: public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
{
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind
{
typedef cxx11_allocator<U, Flags> other;
typedef cxx11_allocator<U, Flags> other;
};
#endif
@@ -268,32 +268,32 @@ struct cxx11_allocator<T, Flags,
// to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const
{
return force_equal_allocator_value || (this->tag_ == x.tag_);
return force_equal_allocator_value || (this->tag_ == x.tag_);
}
bool operator!=(cxx11_allocator const& x) const { return !(*this == x); }
};
};
template <typename T, typename Flags>
struct cxx11_allocator<T, Flags,
template <typename T, typename Flags>
struct cxx11_allocator<T, Flags,
typename boost::enable_if_c<Flags::is_select_on_copy>::type>
: public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>,
public move_allocator_base<Flags>,
Flags
{
{
cxx11_allocator select_on_container_copy_construction() const
{
cxx11_allocator tmp(*this);
++tmp.selected_;
return tmp;
cxx11_allocator tmp(*this);
++tmp.selected_;
return tmp;
}
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind
{
typedef cxx11_allocator<U, Flags> other;
typedef cxx11_allocator<U, Flags> other;
};
#endif
@@ -311,34 +311,34 @@ struct cxx11_allocator<T, Flags,
// to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const
{
return force_equal_allocator_value || (this->tag_ == x.tag_);
return force_equal_allocator_value || (this->tag_ == x.tag_);
}
bool operator!=(cxx11_allocator const& x) const { return !(*this == x); }
};
};
template <typename T, typename Flags>
bool equivalent_impl(cxx11_allocator<T, Flags> const& x,
template <typename T, typename Flags>
bool equivalent_impl(cxx11_allocator<T, Flags> const& x,
cxx11_allocator<T, Flags> const& y, test::derived_type)
{
{
return x.tag_ == y.tag_;
}
}
// Function to check how many times an allocator has been selected,
// return 0 for other allocators.
// Function to check how many times an allocator has been selected,
// return 0 for other allocators.
struct convert_from_anything
{
struct convert_from_anything
{
template <typename T> convert_from_anything(T const&) {}
};
};
inline int selected_count(convert_from_anything) { return 0; }
inline int selected_count(convert_from_anything) { return 0; }
template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x)
{
template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x)
{
return x.selected_;
}
}
}
#endif
+433 -406
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -7,11 +7,11 @@
#define BOOST_UNORDERED_TEST_OBJECTS_FWD_HEADER
namespace test {
class object;
class hash;
class less;
class equal_to;
template <class T> class allocator;
class object;
class hash;
class less;
class equal_to;
template <class T> class allocator;
}
#endif
+442 -423
View File
File diff suppressed because it is too large Load Diff
+265 -245
View File
@@ -14,25 +14,25 @@
#include <cstddef>
namespace test {
// Note that the default hash function will work for any equal_to (but not
// very well).
class object;
class movable;
class implicitly_convertible;
class hash;
class less;
class equal_to;
template <class T> class allocator1;
template <class T> class allocator2;
object generate(object const*, random_generator);
movable generate(movable const*, random_generator);
implicitly_convertible generate(
// Note that the default hash function will work for any equal_to (but not
// very well).
class object;
class movable;
class implicitly_convertible;
class hash;
class less;
class equal_to;
template <class T> class allocator1;
template <class T> class allocator2;
object generate(object const*, random_generator);
movable generate(movable const*, random_generator);
implicitly_convertible generate(
implicitly_convertible const*, random_generator);
inline void ignore_variable(void const*) {}
inline void ignore_variable(void const*) {}
class object : private counted_object
{
class object : private counted_object
{
friend class hash;
friend class equal_to;
friend class less;
@@ -43,40 +43,40 @@ class object : private counted_object
~object()
{
tag1_ = -1;
tag2_ = -1;
tag1_ = -1;
tag2_ = -1;
}
friend bool operator==(object const& x1, object const& x2)
{
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
}
friend bool operator!=(object const& x1, object const& x2)
{
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
}
friend bool operator<(object const& x1, object const& x2)
{
return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend object generate(object const*, random_generator g)
{
int* x = 0;
return object(generate(x, g), generate(x, g));
int* x = 0;
return object(generate(x, g), generate(x, g));
}
friend std::ostream& operator<<(std::ostream& out, object const& o)
{
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
}
};
};
class movable : private counted_object
{
class movable : private counted_object
{
friend class hash;
friend class equal_to;
friend class less;
@@ -89,74 +89,74 @@ class movable : private counted_object
movable(movable const& x)
: counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{
BOOST_TEST(x.tag1_ != -1);
BOOST_TEST(x.tag1_ != -1);
}
movable(BOOST_RV_REF(movable) x)
: counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{
BOOST_TEST(x.tag1_ != -1);
x.tag1_ = -1;
x.tag2_ = -1;
BOOST_TEST(x.tag1_ != -1);
x.tag1_ = -1;
x.tag2_ = -1;
}
movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment
{
BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_;
tag2_ = x.tag2_;
return *this;
BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_;
tag2_ = x.tag2_;
return *this;
}
movable& operator=(BOOST_RV_REF(movable) x) // Move assignment
{
BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_;
tag2_ = x.tag2_;
x.tag1_ = -1;
x.tag2_ = -1;
return *this;
BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_;
tag2_ = x.tag2_;
x.tag1_ = -1;
x.tag2_ = -1;
return *this;
}
~movable()
{
tag1_ = -1;
tag2_ = -1;
tag1_ = -1;
tag2_ = -1;
}
friend bool operator==(movable const& x1, movable const& x2)
{
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
}
friend bool operator!=(movable const& x1, movable const& x2)
{
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
}
friend bool operator<(movable const& x1, movable const& x2)
{
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
}
friend movable generate(movable const*, random_generator g)
{
int* x = 0;
return movable(generate(x, g), generate(x, g));
int* x = 0;
return movable(generate(x, g), generate(x, g));
}
friend std::ostream& operator<<(std::ostream& out, movable const& o)
{
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
}
};
};
class implicitly_convertible : private counted_object
{
class implicitly_convertible : private counted_object
{
int tag1_, tag2_;
public:
@@ -170,92 +170,94 @@ class implicitly_convertible : private counted_object
operator movable() const { return movable(tag1_, tag2_); }
friend implicitly_convertible generate(
implicitly_convertible const*, random_generator g)
implicitly_convertible const*, random_generator g)
{
int* x = 0;
return implicitly_convertible(generate(x, g), generate(x, g));
int* x = 0;
return implicitly_convertible(generate(x, g), generate(x, g));
}
friend std::ostream& operator<<(
std::ostream& out, implicitly_convertible const& o)
std::ostream& out, implicitly_convertible const& o)
{
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
}
};
};
// Note: This is a deliberately bad hash function.
class hash
{
// Note: This is a deliberately bad hash function.
class hash
{
int type_;
public:
explicit hash(int t = 0) : type_(t) {}
hash() : type_(0) {}
explicit hash(int t) : type_(t) {}
std::size_t operator()(object const& x) const
{
int result;
switch (type_) {
case 1:
result = x.tag1_;
break;
case 2:
result = x.tag2_;
break;
default:
result = x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
int result;
switch (type_) {
case 1:
result = x.tag1_;
break;
case 2:
result = x.tag2_;
break;
default:
result = x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
}
std::size_t operator()(movable const& x) const
{
int result;
switch (type_) {
case 1:
result = x.tag1_;
break;
case 2:
result = x.tag2_;
break;
default:
result = x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
int result;
switch (type_) {
case 1:
result = x.tag1_;
break;
case 2:
result = x.tag2_;
break;
default:
result = x.tag1_ + x.tag2_;
}
return static_cast<std::size_t>(result);
}
std::size_t operator()(int x) const
{
int result;
switch (type_) {
case 1:
result = x;
break;
case 2:
result = x * 7;
break;
default:
result = x * 256;
}
return static_cast<std::size_t>(result);
int result;
switch (type_) {
case 1:
result = x;
break;
case 2:
result = x * 7;
break;
default:
result = x * 256;
}
return static_cast<std::size_t>(result);
}
friend bool operator==(hash const& x1, hash const& x2)
{
return x1.type_ == x2.type_;
return x1.type_ == x2.type_;
}
friend bool operator!=(hash const& x1, hash const& x2)
{
return x1.type_ != x2.type_;
return x1.type_ != x2.type_;
}
};
};
std::size_t hash_value(test::object const& x) { return hash()(x); }
std::size_t hash_value(test::object const& x) { return hash()(x); }
std::size_t hash_value(test::movable const& x) { return hash()(x); }
std::size_t hash_value(test::movable const& x) { return hash()(x); }
class less
{
class less
{
int type_;
public:
@@ -263,87 +265,89 @@ class less
bool operator()(object const& x1, object const& x2) const
{
switch (type_) {
case 1:
return x1.tag1_ < x2.tag1_;
case 2:
return x1.tag2_ < x2.tag2_;
default:
return x1 < x2;
}
switch (type_) {
case 1:
return x1.tag1_ < x2.tag1_;
case 2:
return x1.tag2_ < x2.tag2_;
default:
return x1 < x2;
}
}
bool operator()(movable const& x1, movable const& x2) const
{
switch (type_) {
case 1:
return x1.tag1_ < x2.tag1_;
case 2:
return x1.tag2_ < x2.tag2_;
default:
return x1 < x2;
}
switch (type_) {
case 1:
return x1.tag1_ < x2.tag1_;
case 2:
return x1.tag2_ < x2.tag2_;
default:
return x1 < x2;
}
}
std::size_t operator()(int x1, int x2) const { return x1 < x2; }
friend bool operator==(less const& x1, less const& x2)
{
return x1.type_ == x2.type_;
return x1.type_ == x2.type_;
}
};
};
class equal_to
{
class equal_to
{
int type_;
public:
explicit equal_to(int t = 0) : type_(t) {}
equal_to() : type_(0) {}
explicit equal_to(int t) : type_(t) {}
bool operator()(object const& x1, object const& x2) const
{
switch (type_) {
case 1:
return x1.tag1_ == x2.tag1_;
case 2:
return x1.tag2_ == x2.tag2_;
default:
return x1 == x2;
}
switch (type_) {
case 1:
return x1.tag1_ == x2.tag1_;
case 2:
return x1.tag2_ == x2.tag2_;
default:
return x1 == x2;
}
}
bool operator()(movable const& x1, movable const& x2) const
{
switch (type_) {
case 1:
return x1.tag1_ == x2.tag1_;
case 2:
return x1.tag2_ == x2.tag2_;
default:
return x1 == x2;
}
switch (type_) {
case 1:
return x1.tag1_ == x2.tag1_;
case 2:
return x1.tag2_ == x2.tag2_;
default:
return x1 == x2;
}
}
std::size_t operator()(int x1, int x2) const { return x1 == x2; }
friend bool operator==(equal_to const& x1, equal_to const& x2)
{
return x1.type_ == x2.type_;
return x1.type_ == x2.type_;
}
friend bool operator!=(equal_to const& x1, equal_to const& x2)
{
return x1.type_ != x2.type_;
return x1.type_ != x2.type_;
}
friend less create_compare(equal_to x) { return less(x.type_); }
};
};
// allocator1 only has the old fashioned 'construct' method and has
// a few less typedefs. allocator2 uses a custom pointer class.
// allocator1 only has the old fashioned 'construct' method and has
// a few less typedefs. allocator2 uses a custom pointer class.
template <class T> class allocator1
{
template <class T> class allocator1
{
public:
int tag_;
@@ -351,61 +355,76 @@ template <class T> class allocator1
template <class U> struct rebind
{
typedef allocator1<U> other;
typedef allocator1<U> other;
};
explicit allocator1(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
allocator1() : tag_(0) { detail::tracker.allocator_ref(); }
explicit allocator1(int t) : tag_(t) { detail::tracker.allocator_ref(); }
template <class Y> allocator1(allocator1<Y> const& x) : tag_(x.tag_)
{
detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
allocator1(allocator1 const& x) : tag_(x.tag_)
{
detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
~allocator1() { detail::tracker.allocator_unref(); }
T* allocate(std::size_t n)
{
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
T* allocate(std::size_t n, void const*)
{
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(T* p, std::size_t n)
{
detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_);
::operator delete((void*)p);
detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_);
::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);
// 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_; }
@@ -413,18 +432,18 @@ template <class T> class allocator1
enum
{
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
};
};
};
template <class T> class ptr;
template <class T> class const_ptr;
template <class T> class ptr;
template <class T> class const_ptr;
struct void_ptr
{
struct void_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T> friend class ptr;
@@ -444,10 +463,10 @@ struct void_ptr
bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
};
};
class void_const_ptr
{
class void_const_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T> friend class const_ptr;
@@ -470,10 +489,10 @@ class void_const_ptr
bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
};
};
template <class T> class ptr
{
template <class T> class ptr
{
friend class allocator2<T>;
friend class const_ptr<T>;
friend struct void_ptr;
@@ -481,6 +500,7 @@ template <class T> class ptr
T* ptr_;
ptr(T* x) : ptr_(x) {}
public:
ptr() : ptr_(0) {}
explicit ptr(void_ptr const& x) : ptr_((T*)x.ptr_) {}
@@ -489,14 +509,14 @@ template <class T> class ptr
T* operator->() const { return ptr_; }
ptr& operator++()
{
++ptr_;
return *this;
++ptr_;
return *this;
}
ptr operator++(int)
{
ptr tmp(*this);
++ptr_;
return tmp;
ptr tmp(*this);
++ptr_;
return tmp;
}
ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr<T>(s + p.ptr_); }
@@ -513,16 +533,17 @@ template <class T> class ptr
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
};
};
template <class T> class const_ptr
{
template <class T> class const_ptr
{
friend class allocator2<T>;
friend struct const_void_ptr;
T const* ptr_;
const_ptr(T const* ptr) : ptr_(ptr) {}
public:
const_ptr() : ptr_(0) {}
const_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
@@ -532,19 +553,19 @@ template <class T> class const_ptr
T const* operator->() const { return ptr_; }
const_ptr& operator++()
{
++ptr_;
return *this;
++ptr_;
return *this;
}
const_ptr operator++(int)
{
const_ptr tmp(*this);
++ptr_;
return tmp;
const_ptr tmp(*this);
++ptr_;
return tmp;
}
const_ptr operator+(std::ptrdiff_t s) const { return const_ptr(ptr_ + s); }
friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
{
return ptr<T>(s + p.ptr_);
return ptr<T>(s + p.ptr_);
}
T const& operator[](int s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
@@ -556,10 +577,10 @@ template <class T> class const_ptr
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
};
};
template <class T> class allocator2
{
template <class T> class allocator2
{
#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
#else
@@ -580,22 +601,21 @@ template <class T> class allocator2
template <class U> struct rebind
{
typedef allocator2<U> other;
typedef allocator2<U> other;
};
explicit allocator2(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
allocator2() : tag_(0) { detail::tracker.allocator_ref(); }
explicit allocator2(int t) : tag_(t) { detail::tracker.allocator_ref(); }
template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
{
detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
allocator2(allocator2 const& x) : tag_(x.tag_)
{
detail::tracker.allocator_ref();
detail::tracker.allocator_ref();
}
~allocator2() { detail::tracker.allocator_unref(); }
@@ -606,47 +626,47 @@ template <class T> class allocator2
pointer allocate(size_type n)
{
pointer p(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)p.ptr_, n, sizeof(T), tag_);
return p;
pointer p(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)p.ptr_, n, sizeof(T), tag_);
return p;
}
pointer allocate(size_type n, void const*)
{
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr;
}
void deallocate(pointer p, size_type n)
{
detail::tracker.track_deallocate((void*)p.ptr_, n, sizeof(T), tag_);
::operator delete((void*)p.ptr_);
detail::tracker.track_deallocate((void*)p.ptr_, n, sizeof(T), tag_);
::operator delete((void*)p.ptr_);
}
void construct(T* p, T const& t)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t);
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
{
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...);
detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...);
}
#endif
void destroy(T* p)
{
detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T();
detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const
{
return (std::numeric_limits<size_type>::max)();
return (std::numeric_limits<size_type>::max)();
}
bool operator==(allocator2 const& x) const { return tag_ == x.tag_; }
@@ -655,26 +675,26 @@ template <class T> class allocator2
enum
{
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
is_select_on_copy = false,
is_propagate_on_swap = false,
is_propagate_on_assign = false,
is_propagate_on_move = false
};
};
};
template <class T>
bool equivalent_impl(
template <class T>
bool equivalent_impl(
allocator1<T> const& x, allocator1<T> const& y, test::derived_type)
{
{
return x == y;
}
}
template <class T>
bool equivalent_impl(
template <class T>
bool equivalent_impl(
allocator2<T> const& x, allocator2<T> const& y, test::derived_type)
{
{
return x == y;
}
}
}
#endif
+178 -173
View File
@@ -3,7 +3,7 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/detail/lightweight_test.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
@@ -12,76 +12,76 @@
// Boilerplate
#define ALLOCATOR_METHODS(name) \
template <typename U> struct rebind \
{ \
typedef name<U> other; \
}; \
template <typename U> struct rebind \
{ \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
T* address(T& r) { return &r; } \
T const* address(T const& r) { return &r; } \
T* allocate(std::size_t n) \
{ \
return static_cast<T*>(::operator new(n * sizeof(T))); \
} \
T* allocate(std::size_t n, void const*) \
{ \
return static_cast<T*>(::operator new(n * sizeof(T))); \
} \
void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } \
void construct(T* p, T const& t) { new (p) T(t); } \
void destroy(T* p) { p->~T(); } \
std::size_t max_size() const \
{ \
return (std::numeric_limits<std::size_t>::max)(); \
} \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
name() {} \
template <typename Y> name(name<Y> const&) {} \
T* address(T& r) { return &r; } \
T const* address(T const& r) { return &r; } \
T* allocate(std::size_t n) \
{ \
return static_cast<T*>(::operator new(n * sizeof(T))); \
} \
T* allocate(std::size_t n, void const*) \
{ \
return static_cast<T*>(::operator new(n * sizeof(T))); \
} \
void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } \
void construct(T* p, T const& t) { new (p) T(t); } \
void destroy(T* p) { p->~T(); } \
std::size_t max_size() const \
{ \
return (std::numeric_limits<std::size_t>::max)(); \
} \
bool operator==(name<T> const&) const { return true; } \
bool operator!=(name<T> const&) const { return false; } \
/**/
#define ALLOCATOR_METHODS_TYPEDEFS(name) \
template <typename U> struct rebind \
{ \
typedef name<U> other; \
}; \
template <typename U> struct rebind \
{ \
typedef name<U> other; \
}; \
\
name() {} \
template <typename Y> name(name<Y> const&) {} \
pointer address(T& r) { return &r; } \
const_pointer address(T const& r) { return &r; } \
pointer allocate(std::size_t n) \
{ \
return pointer(::operator new(n * sizeof(T))); \
} \
pointer allocate(std::size_t n, void const*) \
{ \
return pointer(::operator new(n * sizeof(T))); \
} \
void deallocate(pointer p, std::size_t) { ::operator delete((void*)p); } \
void construct(T* p, T const& t) { new (p) T(t); } \
void destroy(T* p) { p->~T(); } \
size_type max_size() const \
{ \
return (std::numeric_limits<size_type>::max)(); \
} \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
name() {} \
template <typename Y> name(name<Y> const&) {} \
pointer address(T& r) { return &r; } \
const_pointer address(T const& r) { return &r; } \
pointer allocate(std::size_t n) \
{ \
return pointer(::operator new(n * sizeof(T))); \
} \
pointer allocate(std::size_t n, void const*) \
{ \
return pointer(::operator new(n * sizeof(T))); \
} \
void deallocate(pointer p, std::size_t) { ::operator delete((void*)p); } \
void construct(T* p, T const& t) { new (p) T(t); } \
void destroy(T* p) { p->~T(); } \
size_type max_size() const \
{ \
return (std::numeric_limits<size_type>::max)(); \
} \
bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \
/**/
struct yes_type
{
enum
{
value = true
};
enum
{
value = true
};
};
struct no_type
{
enum
{
value = false
};
enum
{
value = false
};
};
// For tracking calls...
@@ -91,193 +91,198 @@ void reset() { selected = 0; }
template <typename Allocator> int call_select()
{
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
Allocator a;
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
Allocator a;
reset();
BOOST_TEST(traits::select_on_container_copy_construction(a) == a);
return selected;
reset();
BOOST_TEST(traits::select_on_container_copy_construction(a) == a);
return selected;
}
// Empty allocator test
template <typename T> struct empty_allocator
{
typedef T value_type;
ALLOCATOR_METHODS(empty_allocator)
typedef T value_type;
ALLOCATOR_METHODS(empty_allocator)
};
void test_empty_allocator()
{
typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 0);
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 0);
}
// allocator 1
template <typename T> struct allocator1
{
typedef T value_type;
ALLOCATOR_METHODS(allocator1)
typedef T value_type;
ALLOCATOR_METHODS(allocator1)
typedef yes_type propagate_on_container_copy_assignment;
typedef yes_type propagate_on_container_move_assignment;
typedef yes_type propagate_on_container_swap;
typedef yes_type propagate_on_container_copy_assignment;
typedef yes_type propagate_on_container_move_assignment;
typedef yes_type propagate_on_container_swap;
typedef yes_type is_always_equal;
allocator1<T> select_on_container_copy_construction() const
{
++selected;
return allocator1<T>();
}
allocator1<T> select_on_container_copy_construction() const
{
++selected;
return allocator1<T>();
}
};
void test_allocator1()
{
typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(traits::propagate_on_container_move_assignment::value);
BOOST_TEST(traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1);
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(traits::propagate_on_container_move_assignment::value);
BOOST_TEST(traits::propagate_on_container_swap::value);
BOOST_TEST(traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}
// allocator 2
template <typename Alloc> struct allocator2_base
{
Alloc select_on_container_copy_construction() const
{
++selected;
return Alloc();
}
Alloc select_on_container_copy_construction() const
{
++selected;
return Alloc();
}
};
template <typename T> struct allocator2 : allocator2_base<allocator2<T> >
{
typedef T value_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef std::size_t size_type;
typedef T value_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef std::size_t size_type;
ALLOCATOR_METHODS(allocator2)
ALLOCATOR_METHODS(allocator2)
typedef no_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
typedef no_type propagate_on_container_swap;
typedef no_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
typedef no_type propagate_on_container_swap;
typedef no_type is_always_equal;
};
void test_allocator2()
{
typedef allocator2<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1);
typedef allocator2<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(!traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}
// allocator 3
template <typename T> struct ptr
{
T* value_;
T* value_;
ptr(void* v) : value_((T*)v) {}
T& operator*() const { return *value_; }
ptr(void* v) : value_((T*)v) {}
T& operator*() const { return *value_; }
};
template <> struct ptr<void>
{
void* value_;
ptr(void* v) : value_(v) {}
void* value_;
ptr(void* v) : value_(v) {}
};
template <> struct ptr<const void>
{
void const* value_;
ptr(void const* v) : value_(v) {}
void const* value_;
ptr(void const* v) : value_(v) {}
};
template <typename T> struct allocator3
{
typedef T value_type;
typedef ptr<T> pointer;
typedef ptr<T const> const_pointer;
typedef unsigned short size_type;
typedef T value_type;
typedef ptr<T> pointer;
typedef ptr<T const> const_pointer;
typedef unsigned short size_type;
ALLOCATOR_METHODS_TYPEDEFS(allocator3)
int x; // Just to make it non-empty, so that is_always_equal is false.
typedef yes_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
ALLOCATOR_METHODS_TYPEDEFS(allocator3)
allocator3<T> select_on_container_copy_construction() const
{
++selected;
return allocator3<T>();
}
typedef yes_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment;
allocator3<T> select_on_container_copy_construction() const
{
++selected;
return allocator3<T>();
}
};
void test_allocator3()
{
typedef allocator3<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, unsigned short>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, ptr<int const> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1);
typedef allocator3<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, unsigned short>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, ptr<int const> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(!traits::is_always_equal::value);
BOOST_TEST(call_select<allocator>() == 1);
}
int main()
{
test_empty_allocator();
test_allocator1();
test_allocator2();
test_allocator3();
return boost::report_errors();
test_empty_allocator();
test_allocator1();
test_allocator2();
test_allocator3();
return boost::report_errors();
}
+170 -175
View File
@@ -17,261 +17,257 @@
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include <iostream>
#if defined(BOOST_MSVC)
#pragma warning(disable : 4127) // conditional expression is constant
#endif
namespace assign_tests {
test::seed_t initialize_seed(96785);
test::seed_t initialize_seed(96785);
template <class T> void assign_tests1(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
template <class T> void assign_tests1(T*, test::random_generator generator)
{
typename T::hasher hf;
typename T::key_equal eq;
std::cerr << "assign_tests1.1\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n";
{
test::check_instances check_;
test::check_instances check_;
T x;
x = x;
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
T x;
x = x;
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
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_;
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
test::ordered<T> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end());
test::ordered<T> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end());
x = x;
tracker.compare(x);
x = x;
tracker.compare(x);
T y;
y.max_load_factor(x.max_load_factor() / 20);
float mlf = x.max_load_factor();
y = x;
tracker.compare(x);
tracker.compare(y);
BOOST_TEST(x.max_load_factor() == mlf);
BOOST_TEST(y.max_load_factor() == mlf);
BOOST_TEST(y.load_factor() <= y.max_load_factor());
T y;
y.max_load_factor(x.max_load_factor() / 20);
float mlf = x.max_load_factor();
y = x;
tracker.compare(x);
tracker.compare(y);
BOOST_TEST(x.max_load_factor() == mlf);
BOOST_TEST(y.max_load_factor() == mlf);
BOOST_TEST(y.load_factor() <= y.max_load_factor());
}
}
}
template <class T> void assign_tests2(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
BOOST_DEDUCED_TYPENAME T::key_equal eq1(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq2(2);
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
template <class T> void assign_tests2(T*, test::random_generator generator)
{
typename T::hasher hf1(1);
typename T::hasher hf2(2);
typename T::key_equal eq1(1);
typename T::key_equal eq2(2);
typename T::allocator_type al1(1);
typename T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
typedef 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_;
test::check_instances check_;
T x1(0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
test::check_container(x1, x2);
T x1(0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
test::check_container(x1, x2);
}
std::cerr << "assign_tests2.1\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x1(v.begin(), v.end(), 0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
test::check_container(x1, v);
test::check_container(x2, v);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
test::random_values<T> v(1000, generator);
T x1(v.begin(), v.end(), 0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
test::check_container(x1, v);
test::check_container(x2, v);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
std::cerr << "assign_tests2.1a\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1a\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v1(0, generator);
test::random_values<T> v2(1000, generator);
T x1(0, hf2, eq2);
T x2(v2.begin(), v2.end(), 0, hf1, eq1);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
test::random_values<T> v1(0, generator);
test::random_values<T> v2(1000, generator);
T x1(0, hf2, eq2);
T x2(v2.begin(), v2.end(), 0, hf1, eq1);
x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
std::cerr << "assign_tests2.2\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.2\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v1(100, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
test::random_values<T> v1(100, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
std::cerr << "assign_tests2.3\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.3\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v1(100, generator), v2(1000, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
test::random_values<T> v1(100, generator), v2(1000, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
std::cerr << "assign_tests2.4\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.4\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v1(1000, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
test::random_values<T> v1(1000, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
}
test::check_container(x1, v1);
test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
}
}
}
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_set_prop_assign;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multiset_prop_assign;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_map_prop_assign;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multimap_prop_assign;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_set_no_prop_assign;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multiset_no_prop_assign;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_map_no_prop_assign;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multimap_no_prop_assign;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
template <typename T> bool is_propagate(T*)
{
template <typename T> bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_assign;
}
}
UNORDERED_AUTO_TEST(check_traits)
{
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_assign));
BOOST_TEST(!is_propagate(test_set_no_prop_assign));
}
}
UNORDERED_TEST(assign_tests1,
UNORDERED_TEST(assign_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(
test_multimap_prop_assign)(test_set_no_prop_assign)(
test_multiset_no_prop_assign)(test_map_no_prop_assign)(
test_multimap_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(
test_multimap_prop_assign)(test_set_no_prop_assign)(
test_multiset_no_prop_assign)(test_map_no_prop_assign)(
test_multimap_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
UNORDERED_TEST(
assign_tests2, ((test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_assign)(test_multiset_prop_assign)(
test_map_prop_assign)(test_multimap_prop_assign)(
test_set_no_prop_assign)(test_multiset_no_prop_assign)(
test_map_no_prop_assign)(test_multimap_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
test_set_prop_assign)(test_multiset_prop_assign)(
test_map_prop_assign)(test_multimap_prop_assign)(
test_set_no_prop_assign)(test_multiset_no_prop_assign)(
test_map_no_prop_assign)(test_multimap_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_default_initializer_list)
{
std::cerr << "Initializer List Tests\n";
UNORDERED_AUTO_TEST (assign_default_initializer_list) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
std::initializer_list<std::pair<int const, int> > init;
boost::unordered_map<int, int> x1;
x1[25] = 3;
@@ -279,14 +275,13 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list)
BOOST_TEST(!x1.empty());
x1 = init;
BOOST_TEST(x1.empty());
}
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
std::cerr << "Initializer List Tests\n";
UNORDERED_AUTO_TEST (assign_initializer_list) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
boost::unordered_set<int> x;
x.insert(10);
@@ -294,7 +289,7 @@ UNORDERED_AUTO_TEST(assign_initializer_list)
x = {1, 2, -10};
BOOST_TEST(x.find(10) == x.end());
BOOST_TEST(x.find(-10) != x.end());
}
}
#endif
}
+28 -6
View File
@@ -14,11 +14,25 @@
namespace at_tests {
UNORDERED_AUTO_TEST(at_tests)
{
UNORDERED_AUTO_TEST (at_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x;
boost::unordered_map<std::string, int> const& x_const(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
try {
x.at("one");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range&) {
}
try {
x_const.at("one");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range&) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
@@ -29,17 +43,25 @@ 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;
try {
x.at("three");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) {
x.at("three");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range&) {
}
try {
x_const.at("three");
BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range&) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}
}
RUN_TESTS()
+39 -40
View File
@@ -23,73 +23,72 @@
namespace bucket_tests {
test::seed_t initialize_seed(54635);
test::seed_t initialize_seed(54635);
template <class X> void tests(X*, test::random_generator generator)
{
template <class X> void tests(X*, test::random_generator generator)
{
test::check_instances check_;
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef typename X::size_type size_type;
typedef typename X::const_local_iterator const_local_iterator;
test::random_values<X> v(1000, generator);
X x(v.begin(), v.end());
BOOST_TEST(x.bucket_count() <= x.max_bucket_count());
if (!(x.bucket_count() <= x.max_bucket_count())) {
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
it = v.begin(),
end = v.end();
for (typename test::random_values<X>::const_iterator it = v.begin(),
end = v.end();
it != end; ++it) {
size_type bucket = x.bucket(test::get_key<X>(*it));
size_type bucket = x.bucket(test::get_key<X>(*it));
BOOST_TEST(bucket < x.bucket_count());
if (bucket < x.bucket_count()) {
// lit? lend?? I need a new naming scheme.
const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
while (lit != lend &&
test::get_key<X>(*it) != test::get_key<X>(*lit)) {
++lit;
}
BOOST_TEST(lit != lend);
BOOST_TEST(bucket < x.bucket_count());
if (bucket < x.bucket_count()) {
// lit? lend?? I need a new naming scheme.
const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
while (lit != lend && test::get_key<X>(*it) != test::get_key<X>(*lit)) {
++lit;
}
BOOST_TEST(lit != lend);
}
}
for (size_type i = 0; i < x.bucket_count(); ++i) {
BOOST_TEST(x.bucket_size(i) ==
static_cast<size_type>(std::distance(x.begin(i), x.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x.cbegin(i), x.cend(i))));
X const& x_ref = x;
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x_ref.begin(i), x_ref.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x_ref.cbegin(i), x_ref.cend(i))));
BOOST_TEST(x.bucket_size(i) ==
static_cast<size_type>(std::distance(x.begin(i), x.end(i))));
BOOST_TEST(x.bucket_size(i) ==
static_cast<size_type>(std::distance(x.cbegin(i), x.cend(i))));
X const& x_ref = x;
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x_ref.begin(i), x_ref.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x_ref.cbegin(i), x_ref.cend(i))));
}
}
}
boost::unordered_multimap<test::object, test::object, test::hash,
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,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(tests, ((test_multimap_std_alloc)(test_set)(test_multiset)(
test_map)(test_multimap))((default_generator)(
generate_collisions)(limited_range)))
UNORDERED_TEST(tests,
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(
test_multimap))((default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
+181 -163
View File
@@ -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"
@@ -20,211 +19,230 @@
// Explicit instantiation to catch compile-time errors
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
template class boost::unordered::detail::instantiate_##type
INSTANTIATE(map)<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
test::minimal::allocator<int> >;
INSTANTIATE(multimap)<int const, int const, boost::hash<int>,
std::equal_to<int>, test::minimal::allocator<int> >;
std::equal_to<int>, test::minimal::allocator<int> >;
INSTANTIATE(map)<test::minimal::assignable const,
test::minimal::default_assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
INSTANTIATE(
map)<test::minimal::assignable const, test::minimal::default_assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
UNORDERED_AUTO_TEST (test0) {
test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
value_type;
value_type value(x, x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
test::minimal::allocator<value_type> >
map;
UNORDERED_AUTO_TEST(test0)
{
test::minimal::constructor_param x;
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value);
typedef std::pair<test::minimal::assignable const,
test::minimal::assignable>
value_type;
value_type value(x, x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
std::cout << "Test unordered_map.\n";
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_map<int, int> int_map;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
multimap;
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
map;
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value);
std::cout << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
multimap;
container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(int_multimap2, std::pair<int const, int>(0, 0));
container_test(multimap, value);
container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(int_multimap2, std::pair<int const, int>(0, 0));
container_test(multimap, value);
}
UNORDERED_AUTO_TEST(equality_tests)
{
typedef std::pair<
test::minimal::copy_constructible_equality_comparable const,
test::minimal::copy_constructible_equality_comparable>
value_type;
UNORDERED_AUTO_TEST (equality_tests) {
typedef std::pair<test::minimal::copy_constructible_equality_comparable const,
test::minimal::copy_constructible_equality_comparable>
value_type;
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_map<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
map;
boost::unordered_map<test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
map;
equality_test(int_map);
equality_test(int_map2);
equality_test(map);
equality_test(int_map);
equality_test(int_map2);
equality_test(map);
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
multimap;
boost::unordered_multimap<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
multimap;
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
}
UNORDERED_AUTO_TEST(test1)
{
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::pair<int const, int> map_value(0, 0);
UNORDERED_AUTO_TEST (test1) {
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::pair<int const, int> map_value(0, 0);
std::cout << "Test unordered_map.\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<int, int> map;
boost::unordered_map<int, int> map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
map2;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
map2;
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
unordered_copyable_test(map, value, map_value, hash, equal_to);
unordered_map_functions(map, value, value);
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
unordered_copyable_test(map, value, map_value, hash, equal_to);
unordered_map_functions(map, value, value);
unordered_unique_test(map2, map_value);
unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
unordered_unique_test(map2, map_value);
unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
std::cout << "Test unordered_multimap.\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
boost::unordered_multimap<int, int> multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
multimap2;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
multimap2;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
unordered_copyable_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
unordered_copyable_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
UNORDERED_AUTO_TEST (test2) {
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
map_value_type;
map_value_type map_value(assignable, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map;
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
boost::unordered_map<test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map2;
test::minimal::default_assignable default_assignable;
unordered_map_functions(map2, assignable, default_assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
multimap;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
}
// Test for ambiguity when using key convertible from iterator
// See LWG2059
struct lwg2059_key
{
test::minimal::constructor_param x;
int value;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
template <typename T> lwg2059_key(T v) : value(v) {}
};
typedef std::pair<test::minimal::assignable const,
test::minimal::assignable>
map_value_type;
map_value_type map_value(assignable, assignable);
std::size_t hash_value(lwg2059_key x)
{
return static_cast<std::size_t>(x.value);
}
std::cout << "Test unordered_map.\n";
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map;
UNORDERED_AUTO_TEST (lwg2059) {
{
boost::unordered_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
boost::unordered_map<test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map2;
test::minimal::default_assignable default_assignable;
unordered_map_functions(map2, assignable, default_assignable);
std::cout << "Test unordered_multimap.\n";
boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
multimap;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
{
boost::unordered_multimap<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
}
RUN_TESTS()
+218 -198
View File
@@ -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"
@@ -20,274 +19,295 @@
// Explicit instantiation to catch compile-time errors
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
template class boost::unordered::detail::instantiate_##type
INSTANTIATE(set)<int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
test::minimal::allocator<int> >;
INSTANTIATE(multiset)<int const, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
test::minimal::allocator<int> >;
INSTANTIATE(set)<test::minimal::assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
INSTANTIATE(multiset)<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
UNORDERED_AUTO_TEST (test0) {
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
test::minimal::allocator<test::minimal::assignable> >
set;
UNORDERED_AUTO_TEST(test0)
{
test::minimal::constructor_param x;
container_test(int_set, 0);
container_test(int_set2, 0);
container_test(set, assignable);
test::minimal::assignable assignable(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
std::cout << "Test unordered_set.\n";
boost::unordered_multiset<int> int_multiset;
boost::unordered_set<int> int_set;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
boost::unordered_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
container_test(int_set, 0);
container_test(int_set2, 0);
container_test(set, assignable);
std::cout << "Test unordered_multiset.\n";
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
}
UNORDERED_AUTO_TEST(equality_tests)
{
typedef test::minimal::copy_constructible_equality_comparable value_type;
UNORDERED_AUTO_TEST (equality_tests) {
typedef test::minimal::copy_constructible_equality_comparable value_type;
boost::unordered_set<int> int_set;
boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_set<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
set;
boost::unordered_set<test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
set;
equality_test(int_set);
equality_test(int_set2);
equality_test(set);
equality_test(int_set);
equality_test(int_set2);
equality_test(set);
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
multiset;
boost::unordered_multiset<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
multiset;
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
}
UNORDERED_AUTO_TEST(test1)
{
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
UNORDERED_AUTO_TEST (test1) {
boost::hash<int> hash;
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;
boost::unordered_set<int> set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
set2;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
set2;
unordered_unique_test(set, value);
unordered_set_test(set, value);
unordered_copyable_test(set, value, value, hash, equal_to);
unordered_unique_test(set, value);
unordered_set_test(set, value);
unordered_copyable_test(set, value, value, hash, equal_to);
unordered_unique_test(set2, value);
unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to);
unordered_unique_test(set2, value);
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;
boost::unordered_multiset<int> multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
multiset2;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
multiset2;
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
unordered_copyable_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
unordered_copyable_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to);
}
UNORDERED_AUTO_TEST(test2)
{
test::minimal::constructor_param x;
UNORDERED_AUTO_TEST (test2) {
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
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>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
boost::unordered_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
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";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
}
UNORDERED_AUTO_TEST(movable1_tests)
{
test::minimal::constructor_param x;
UNORDERED_AUTO_TEST (movable1_tests) {
test::minimal::constructor_param x;
test::minimal::movable1 movable1(x);
test::minimal::hash<test::minimal::movable1> hash(x);
test::minimal::equal_to<test::minimal::movable1> equal_to(x);
test::minimal::movable1 movable1(x);
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>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
set;
boost::unordered_set<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
set;
// unordered_unique_test(set, movable1);
unordered_set_test(set, movable1);
unordered_movable_test(set, movable1, movable1, hash, equal_to);
// unordered_unique_test(set, movable1);
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>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
multiset;
boost::unordered_multiset<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
multiset;
// unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
// unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
}
UNORDERED_AUTO_TEST(movable2_tests)
{
test::minimal::constructor_param x;
UNORDERED_AUTO_TEST (movable2_tests) {
test::minimal::constructor_param x;
test::minimal::movable2 movable2(x);
test::minimal::hash<test::minimal::movable2> hash(x);
test::minimal::equal_to<test::minimal::movable2> equal_to(x);
test::minimal::movable2 movable2(x);
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>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
set;
boost::unordered_set<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
set;
// unordered_unique_test(set, movable2);
unordered_set_test(set, movable2);
unordered_movable_test(set, movable2, movable2, hash, equal_to);
// unordered_unique_test(set, movable2);
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>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
multiset;
boost::unordered_multiset<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
multiset;
// unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
// unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
}
UNORDERED_AUTO_TEST(destructible_tests)
UNORDERED_AUTO_TEST (destructible_tests) {
test::minimal::constructor_param x;
test::minimal::destructible destructible(x);
test::minimal::hash<test::minimal::destructible> hash(x);
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
set;
unordered_destructible_test(set);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
multiset;
unordered_destructible_test(multiset);
}
// Test for ambiguity when using key convertible from iterator
// See LWG2059
struct lwg2059_key
{
test::minimal::constructor_param x;
int value;
test::minimal::destructible destructible(x);
test::minimal::hash<test::minimal::destructible> hash(x);
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
template <typename T> lwg2059_key(T v) : value(v) {}
};
std::cout << "Test unordered_set.\n";
std::size_t hash_value(lwg2059_key x)
{
return static_cast<std::size_t>(x.value);
}
boost::unordered_set<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
set;
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
unordered_destructible_test(set);
UNORDERED_AUTO_TEST (lwg2059) {
{
boost::unordered_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
std::cout << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
multiset;
unordered_destructible_test(multiset);
{
boost::unordered_multiset<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
}
RUN_TESTS()
File diff suppressed because it is too large Load Diff
+285 -292
View File
@@ -20,434 +20,427 @@
namespace constructor_tests {
test::seed_t initialize_seed(356730);
test::seed_t initialize_seed(356730);
template <class T> void constructor_tests1(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
template <class T>
void constructor_tests1(T*, test::random_generator generator)
{
typename T::hasher hf;
typename T::key_equal eq;
typename T::allocator_type al;
std::cerr << "Construct 1\n";
UNORDERED_SUB_TEST("Construct 1")
{
test::check_instances check_;
test::check_instances check_;
T x(0, hf, eq);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(0, hf, eq);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr << "Construct 2\n";
UNORDERED_SUB_TEST("Construct 2")
{
test::check_instances check_;
test::check_instances check_;
T x(100, hf);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(100, hf);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr << "Construct 3\n";
UNORDERED_SUB_TEST("Construct 3")
{
test::check_instances check_;
test::check_instances check_;
T x(2000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 2000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(2000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 2000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr << "Construct 4\n";
UNORDERED_SUB_TEST("Construct 4")
{
test::check_instances check_;
test::check_instances check_;
T x;
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x;
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr << "Construct 5\n";
UNORDERED_SUB_TEST("Construct 5")
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr << "Construct 6\n";
UNORDERED_SUB_TEST("Construct 6")
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(10, generator);
T x(v.begin(), v.end(), 10000, hf);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(10, generator);
T x(v.begin(), v.end(), 10000, hf);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr << "Construct 7\n";
UNORDERED_SUB_TEST("Construct 7")
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 100);
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 100);
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr << "Construct 8\n";
UNORDERED_SUB_TEST("Construct 8")
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(1, generator);
T x(v.begin(), v.end());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(1, generator);
T x(v.begin(), v.end());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr << "Construct 9\n";
UNORDERED_SUB_TEST("Construct 9")
{
test::check_instances check_;
test::check_instances check_;
T x(0, hf, eq, al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(0, hf, eq, al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr << "Construct 10\n";
UNORDERED_SUB_TEST("Construct 10")
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq, al);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq, al);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr << "Construct 11\n";
UNORDERED_SUB_TEST("Construct 11")
{
test::check_instances check_;
test::check_instances check_;
T x(al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
T x(al);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
}
}
template <class T>
void constructor_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::key_equal eq1(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq2(2);
BOOST_DEDUCED_TYPENAME T::allocator_type al;
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
template <class T>
void constructor_tests2(T*, test::random_generator const& generator)
{
typename T::hasher hf;
typename T::hasher hf1(1);
typename T::hasher hf2(2);
typename T::key_equal eq;
typename T::key_equal eq1(1);
typename T::key_equal eq2(2);
typename T::allocator_type al;
typename T::allocator_type al1(1);
typename T::allocator_type al2(2);
std::cerr << "Construct 1\n";
UNORDERED_SUB_TEST("Construct 1")
{
test::check_instances check_;
T x(10000, hf1, eq1);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
test::check_instances check_;
T x(10000, hf1, eq1);
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr << "Construct 2\n";
UNORDERED_SUB_TEST("Construct 2")
{
test::check_instances check_;
T x(100, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
test::check_instances check_;
T x(100, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr << "Construct 3\n";
UNORDERED_SUB_TEST("Construct 3")
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr << "Construct 4\n";
UNORDERED_SUB_TEST("Construct 4")
{
test::check_instances check_;
test::random_values<T> v(5, generator);
T x(v.begin(), v.end(), 1000, hf1);
BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
test::check_instances check_;
test::random_values<T> v(5, generator);
T x(v.begin(), v.end(), 1000, hf1);
BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr << "Construct 5\n";
UNORDERED_SUB_TEST("Construct 5")
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf, eq, al1);
T y(x.begin(), x.end(), 0, hf1, eq1, al2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf, eq, al1);
T y(x.begin(), x.end(), 0, hf1, eq1, al2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
std::cerr << "Construct 6\n";
UNORDERED_SUB_TEST("Construct 6")
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf, eq);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf, eq);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
std::cerr << "Construct 7\n";
UNORDERED_SUB_TEST("Construct 7")
{
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
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);
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
v_begin = v.begin(),
v_end = v.end();
T x(test::input_iterator(v_begin), test::input_iterator(v_end), 0, hf1,
eq1);
BOOST_DEDUCED_TYPENAME T::const_iterator x_begin = x.begin(),
x_end = x.end();
T y(test::input_iterator(x_begin), test::input_iterator(x_end), 0, hf2,
eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
test::check_instances check_;
test::random_values<T> v(100, generator);
typename test::random_values<T>::const_iterator v_begin = v.begin(),
v_end = v.end();
T x(test::input_iterator(v_begin), test::input_iterator(v_end), 0, hf1,
eq1);
typename T::const_iterator x_begin = x.begin(), x_end = x.end();
T y(test::input_iterator(x_begin), test::input_iterator(x_end), 0, hf2,
eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
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);
T x(test::copy_iterator(v.begin()), test::copy_iterator(v.end()), 0,
hf1, eq1);
T y(test::copy_iterator(x.begin()), test::copy_iterator(x.end()), 0,
hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(test::copy_iterator(v.begin()), test::copy_iterator(v.end()), 0, hf1,
eq1);
T y(test::copy_iterator(x.begin()), test::copy_iterator(x.end()), 0, hf2,
eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
std::cerr << "Construct 9\n";
UNORDERED_SUB_TEST("Construct 9")
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(100, generator);
T x(50);
BOOST_TEST(x.bucket_count() >= 50);
x.max_load_factor(10);
BOOST_TEST(x.bucket_count() >= 50);
x.insert(v.begin(), v.end());
BOOST_TEST(x.bucket_count() >= 50);
test::check_container(x, v);
test::check_equivalent_keys(x);
test::random_values<T> v(100, generator);
T x(50);
BOOST_TEST(x.bucket_count() >= 50);
x.max_load_factor(10);
BOOST_TEST(x.bucket_count() >= 50);
x.insert(v.begin(), v.end());
BOOST_TEST(x.bucket_count() >= 50);
test::check_container(x, v);
test::check_equivalent_keys(x);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
std::initializer_list<typename T::value_type> list;
std::cerr << "Initializer list construct 1\n";
UNORDERED_SUB_TEST("Initializer list construct 1")
{
test::check_instances check_;
test::check_instances check_;
T x(list);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
T x(list);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
std::cerr << "Initializer list construct 2\n";
UNORDERED_SUB_TEST("Initializer list construct 2")
{
test::check_instances check_;
test::check_instances check_;
T x(list, 1000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
T x(list, 1000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
std::cerr << "Initializer list construct 3\n";
UNORDERED_SUB_TEST("Initializer list construct 3")
{
test::check_instances check_;
test::check_instances check_;
T x(list, 10, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
T x(list, 10, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
std::cerr << "Initializer list construct 4\n";
UNORDERED_SUB_TEST("Initializer list construct 4")
{
test::check_instances check_;
test::check_instances check_;
T x(list, 10, hf1, eq1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
T x(list, 10, hf1, eq1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
std::cerr << "Initializer list construct 5\n";
UNORDERED_SUB_TEST("Initializer list construct 5")
{
test::check_instances check_;
test::check_instances check_;
T x(list, 10, hf1, eq1, al1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
T x(list, 10, hf1, eq1, al1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
}
#endif
}
}
template <class T>
void map_constructor_test(T*, test::random_generator const& generator)
{
std::cerr << "map_constructor_test\n";
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME T::key_type,
BOOST_DEDUCED_TYPENAME T::mapped_type> >
list;
template <class T>
void map_constructor_test(T*, test::random_generator const& generator)
{
typedef test::list<
std::pair<typename T::key_type, typename T::mapped_type> >
list;
test::random_values<T> v(1000, generator);
list l(v.begin(), v.end());
T x(l.begin(), l.end());
test::check_container(x, v);
test::check_equivalent_keys(x);
}
}
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(constructor_tests1,
UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(constructor_tests2,
UNORDERED_TEST(constructor_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_constructor_test,
UNORDERED_TEST(map_constructor_test,
((test_map_std_alloc)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
(default_generator)(generate_collisions)(limited_range)))
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_default_initializer_list)
{
std::cerr << "Initializer List Tests\n";
UNORDERED_AUTO_TEST (test_default_initializer_list) {
std::initializer_list<int> init;
boost::unordered_set<int> x1 = init;
BOOST_TEST(x1.empty());
}
}
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_initializer_list)
{
std::cerr << "Initializer List Tests\n";
UNORDERED_AUTO_TEST (test_initializer_list) {
boost::unordered_set<int> x1 = {2, 10, 45, -5};
BOOST_TEST(x1.find(10) != x1.end());
BOOST_TEST(x1.find(46) == x1.end());
}
}
#endif
}
RUN_TESTS()
RUN_TESTS_QUIET()
+120 -120
View File
@@ -22,188 +22,188 @@ test::seed_t initialize_seed(9063);
namespace copy_tests {
template <class T>
void copy_construct_tests1(T*, test::random_generator const& generator)
{
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
template <class T>
void copy_construct_tests1(T*, test::random_generator const& generator)
{
typedef typename T::allocator_type allocator_type;
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
typename T::hasher hf;
typename T::key_equal eq;
typename T::allocator_type al;
{
test::check_instances check_;
test::check_instances check_;
T x;
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
T x;
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
T x(v.begin(), v.end());
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::check_instances check_;
// In this test I drop the original containers max load factor, so it
// is much lower than the load factor. The hash table is not allowed
// to rehash, but the destination container should probably allocate
// enough buckets to decrease the load factor appropriately.
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
x.max_load_factor(x.load_factor() / 4);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
// This isn't guaranteed:
BOOST_TEST(y.load_factor() < y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
// In this test I drop the original containers max load factor, so it
// is much lower than the load factor. The hash table is not allowed
// to rehash, but the destination container should probably allocate
// enough buckets to decrease the load factor appropriately.
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end());
x.max_load_factor(x.load_factor() / 4);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
// This isn't guaranteed:
BOOST_TEST(y.load_factor() < y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
}
}
template <class T>
void copy_construct_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
template <class T>
void copy_construct_tests2(T*, test::random_generator const& generator)
{
typename T::hasher hf(1);
typename T::key_equal eq(1);
typename T::allocator_type al(1);
typename T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
typedef typename T::allocator_type allocator_type;
{
test::check_instances check_;
test::check_instances check_;
T x(10000, hf, eq, al);
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
T x(10000, hf, eq, al);
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::check_instances check_;
T x(1000, hf, eq, al);
T y(x, al2);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
test::check_equivalent_keys(y);
T x(1000, hf, eq, al);
T y(x, al2);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(500, generator);
test::random_values<T> v(500, generator);
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x, al2);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x, al2);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
}
}
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_set_select_copy;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_multiset_select_copy;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_map_select_copy;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::select_copy> >*
test_multimap_select_copy;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_set_no_select_copy;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multiset_no_select_copy;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_map_no_select_copy;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multimap_no_select_copy;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(copy_construct_tests1,
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests2,
UNORDERED_TEST(copy_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
+352
View File
@@ -0,0 +1,352 @@
// Copyright 2017-2018 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/unordered_map.hpp>
#include <iostream>
#include <vector>
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
struct hash_equals
{
template <typename T> bool operator()(T const& x) const
{
boost::hash<T> hf;
return hf(x);
}
template <typename T> bool operator()(T const& x, T const& y) const
{
std::equal_to<T> eq;
return eq(x, y);
}
};
template <typename T> struct test_allocator
{
typedef T value_type;
test_allocator() = default;
template <typename T2> test_allocator(test_allocator<T2> const&) {}
T* allocate(std::size_t n) const { return (T*)malloc(sizeof(T) * n); }
void deallocate(T* ptr, std::size_t) const { free(ptr); }
bool operator==(test_allocator const&) { return true; }
bool operator!=(test_allocator const&) { return false; }
};
#endif
int main()
{
std::cout << "BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES: "
<< BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES << std::endl;
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
std::vector<std::pair<int, int> > x;
x.push_back(std::make_pair(1, 3));
x.push_back(std::make_pair(5, 10));
test_allocator<std::pair<const int, int> > pair_allocator;
hash_equals f;
// unordered_map
/*
template<class InputIterator,
class Hash = hash<iter_key_t<InputIterator>>,
class Pred = equal_to<iter_key_t<InputIterator>>,
class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
unordered_map(InputIterator, InputIterator, typename see below::size_type =
see below,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
Hash, Pred,
Allocator>;
*/
{
boost::unordered_map m(x.begin(), x.end());
static_assert(
std::is_same<decltype(m), boost::unordered_map<int, int> >::value);
}
/* Ambiguous:
{
boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>());
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
std::hash<int>>>::value);
}
{
boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>(),
std::equal_to<int>());
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
std::hash<int>, std::equal_to<int>>>::value);
}
*/
{
boost::unordered_map m(x.begin(), x.end(), 0, std::hash<int>(),
std::equal_to<int>(), pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_map<int, int, std::hash<int>, std::equal_to<int>,
test_allocator<std::pair<const int, int> > > >::value);
}
/*
template<class Key, class T, class Hash = hash<Key>,
class Pred = equal_to<Key>, class Allocator = allocator<pair<const
Key, T>>>
unordered_map(initializer_list<pair<const Key, T>>,
typename see below::size_type = see below, Hash = Hash(),
Pred = Pred(), Allocator = Allocator())
-> unordered_map<Key, T, Hash, Pred, Allocator>;
*/
{
boost::unordered_map m({std::pair<int const, int>(1, 2)});
static_assert(
std::is_same<decltype(m), boost::unordered_map<int, int> >::value);
}
/* Ambiguous
{
boost::unordered_map m({std::pair<int const, int>(1,2)}, 0,
std::hash<int>());
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
std::hash<int>>>::value);
}
{
boost::unordered_map m({std::pair<int const, int>(1,2)}, 0,
std::hash<int>(), std::equal_to<int>());
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
std::hash<int>, std::equal_to<int>>>::value);
}
*/
{
boost::unordered_map m(
{std::pair<int const, int>(1, 2)}, 0, f, f, pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_map<int, int, hash_equals, hash_equals,
test_allocator<std::pair<const int, int> > > >::value);
}
/*
template<class InputIterator, class Allocator>
unordered_map(InputIterator, InputIterator, typename see below::size_type,
Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
hash<iter_key_t<InputIterator>>,
equal_to<iter_key_t<InputIterator>>,
Allocator>;
*/
/* Ambiguous
{
boost::unordered_map m(x.begin(), x.end(), 0u, pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/*
template<class InputIterator, class Allocator>
unordered_map(InputIterator, InputIterator, Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
hash<iter_key_t<InputIterator>>,
equal_to<iter_key_t<InputIterator>>,
Allocator>;
*/
/* No constructor:
{
boost::unordered_map m(x.begin(), x.end(), pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/*
template<class InputIterator, class Hash, class Allocator>
unordered_map(InputIterator, InputIterator, typename see below::size_type,
Hash, Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
Hash,
equal_to<iter_key_t<InputIterator>>, Allocator>;
*/
/* Ambiguous
{
boost::unordered_map m(x.begin(), x.end(), 0u, f, pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_map<int, int,
hash_equals, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/*
template<class Key, class T, typename Allocator>
unordered_map(initializer_list<pair<const Key, T>>, typename see
below::size_type,
Allocator)
-> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
*/
/* Ambiguous
{
boost::unordered_map m({std::pair<int const, int>(1,2)}, 0, pair_allocator);
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/*
template<class Key, class T, typename Allocator>
unordered_map(initializer_list<pair<const Key, T>>, Allocator)
-> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
*/
{
boost::unordered_map m({std::pair<int const, int>(1, 2)}, pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test_allocator<std::pair<const int, int> > > >::value);
}
/*
template<class Key, class T, class Hash, class Allocator>
unordered_map(initializer_list<pair<const Key, T>>, typename see
below::size_type, Hash,
Allocator)
-> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
*/
/* Ambiguous
{
boost::unordered_map m({std::pair<int const, int>(1,2)}, 0, f,
pair_allocator);
static_assert(std::is_same<decltype(m),boost::unordered_map<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
// unordered_multimap
{
boost::unordered_multimap m(x.begin(), x.end());
static_assert(
std::is_same<decltype(m), boost::unordered_multimap<int, int> >::value);
}
/* Ambiguous:
{
boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>());
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
std::hash<int>>>::value);
}
{
boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>(),
std::equal_to<int>());
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
std::hash<int>, std::equal_to<int>>>::value);
}
*/
{
boost::unordered_multimap m(x.begin(), x.end(), 0, std::hash<int>(),
std::equal_to<int>(), pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>,
test_allocator<std::pair<const int, int> > > >::value);
}
{
boost::unordered_multimap m({std::pair<int const, int>(1, 2)});
static_assert(
std::is_same<decltype(m), boost::unordered_multimap<int, int> >::value);
}
/* Ambiguous
{
boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
std::hash<int>());
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
std::hash<int>>>::value);
}
{
boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
std::hash<int>(), std::equal_to<int>());
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
std::hash<int>, std::equal_to<int>>>::value);
}
*/
{
boost::unordered_multimap m(
{std::pair<int const, int>(1, 2)}, 0, f, f, pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_multimap<int, int, hash_equals, hash_equals,
test_allocator<std::pair<const int, int> > > >::value);
}
/* Ambiguous
{
boost::unordered_multimap m(x.begin(), x.end(), 0u, pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/* No constructor:
{
boost::unordered_multimap m(x.begin(), x.end(), pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
/* Ambiguous
{
boost::unordered_multimap m(x.begin(), x.end(), 0u, f, pair_allocator);
static_assert(std::is_same<decltype(m), boost::unordered_multimap<int, int,
hash_equals, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
{
boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0,
pair_allocator);
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
{
boost::unordered_multimap m(
{std::pair<int const, int>(1, 2)}, pair_allocator);
static_assert(std::is_same<decltype(m),
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test_allocator<std::pair<const int, int> > > >::value);
}
/* Ambiguous
{
boost::unordered_multimap m({std::pair<int const, int>(1,2)}, 0, f,
pair_allocator);
static_assert(std::is_same<decltype(m),boost::unordered_multimap<int, int,
boost::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int,
int>>>>::value);
}
*/
#endif
}
+101
View File
@@ -0,0 +1,101 @@
// Copyright 2017 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include <map>
// Pretty inefficient, but the test is fast enough.
// Might be too slow if we had larger primes?
bool is_prime(std::size_t x)
{
if (x == 2) {
return true;
} else if (x == 1 || x % 2 == 0) {
return false;
} else {
// y*y <= x had rounding errors, so instead use y <= (x/y).
for (std::size_t y = 3; y <= (x / y); y += 2) {
if (x % y == 0) {
return false;
break;
}
}
return true;
}
}
void test_next_prime(std::size_t value)
{
std::size_t x = boost::unordered::detail::next_prime(value);
BOOST_TEST(is_prime(x));
BOOST_TEST(x >= value);
}
void test_prev_prime(std::size_t value)
{
std::size_t x = boost::unordered::detail::prev_prime(value);
BOOST_TEST(is_prime(x));
BOOST_TEST(x <= value);
if (x > value) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x << "," << value << std::endl;
}
}
UNORDERED_AUTO_TEST (next_prime_test) {
BOOST_TEST(!is_prime(0));
BOOST_TEST(!is_prime(1));
BOOST_TEST(is_prime(2));
BOOST_TEST(is_prime(3));
BOOST_TEST(is_prime(13));
BOOST_TEST(!is_prime(4));
BOOST_TEST(!is_prime(100));
BOOST_TEST(boost::unordered::detail::next_prime(0) > 0);
// test_prev_prime doesn't work for values less than 17.
// Which should be okay, unless an allocator has a really tiny
// max_size?
const std::size_t min_prime = 17;
// test_next_prime doesn't work for values greater than this,
// which might be a problem if you've got terrabytes of memory?
// I seriously doubt the container would work well at such sizes
// regardless.
const std::size_t max_prime = 4294967291ul;
std::size_t i;
BOOST_TEST(is_prime(min_prime));
BOOST_TEST(is_prime(max_prime));
for (i = 0; i < 10000; ++i) {
if (i < min_prime) {
BOOST_TEST(boost::unordered::detail::prev_prime(i) == min_prime);
} else {
test_prev_prime(i);
}
test_next_prime(i);
}
std::size_t last = i - 1;
for (; i > last; last = i, i += i / 5) {
if (i > max_prime) {
BOOST_TEST(boost::unordered::detail::next_prime(i) == max_prime);
} else {
test_next_prime(i);
}
test_prev_prime(i);
}
}
RUN_TESTS()
+115 -120
View File
@@ -19,9 +19,9 @@
// arguments.
namespace emplace_tests {
// Constructible with 2 to 10 arguments
struct emplace_value : private test::counted_object
{
// Constructible with 2 to 10 arguments
struct emplace_value : private test::counted_object
{
typedef int A0;
typedef std::string A1;
typedef char A2;
@@ -59,40 +59,40 @@ struct emplace_value : private test::counted_object
}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, A4 const& b4)
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, A4 const& b4)
: arg_count(5), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5)
A4 const& b4, A5 const& b5)
: arg_count(6), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6)
A4 const& b4, A5 const& b5, A6 const& b6)
: arg_count(7), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7)
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7)
: arg_count(8), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(b7)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8)
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8)
: arg_count(9), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(b7), a8(b8)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8,
A9 const& b9)
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8,
A9 const& b9)
: arg_count(10), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(b7), a8(b8), a9(b9)
{
@@ -100,79 +100,78 @@ struct emplace_value : private test::counted_object
friend std::size_t hash_value(emplace_value const& x)
{
std::size_t r1 = 23894278u;
if (x.arg_count >= 1)
boost::hash_combine(r1, x.a0);
if (x.arg_count >= 2)
boost::hash_combine(r1, x.a1);
if (x.arg_count >= 3)
boost::hash_combine(r1, x.a2);
if (x.arg_count >= 4)
boost::hash_combine(r1, x.a3);
if (x.arg_count >= 5)
boost::hash_combine(r1, x.a4);
if (x.arg_count >= 6)
boost::hash_combine(r1, x.a5);
if (x.arg_count >= 7)
boost::hash_combine(r1, x.a6);
if (x.arg_count >= 8)
boost::hash_combine(r1, x.a7);
if (x.arg_count >= 9)
boost::hash_combine(r1, x.a8);
if (x.arg_count >= 10)
boost::hash_combine(r1, x.a9);
return r1;
std::size_t r1 = 23894278u;
if (x.arg_count >= 1)
boost::hash_combine(r1, x.a0);
if (x.arg_count >= 2)
boost::hash_combine(r1, x.a1);
if (x.arg_count >= 3)
boost::hash_combine(r1, x.a2);
if (x.arg_count >= 4)
boost::hash_combine(r1, x.a3);
if (x.arg_count >= 5)
boost::hash_combine(r1, x.a4);
if (x.arg_count >= 6)
boost::hash_combine(r1, x.a5);
if (x.arg_count >= 7)
boost::hash_combine(r1, x.a6);
if (x.arg_count >= 8)
boost::hash_combine(r1, x.a7);
if (x.arg_count >= 9)
boost::hash_combine(r1, x.a8);
if (x.arg_count >= 10)
boost::hash_combine(r1, x.a9);
return r1;
}
friend bool operator==(emplace_value const& x, emplace_value const& y)
{
if (x.arg_count != y.arg_count) {
return false;
}
if (x.arg_count >= 1 && x.a0 != y.a0) {
return false;
}
if (x.arg_count >= 2 && x.a1 != y.a1) {
return false;
}
if (x.arg_count >= 3 && x.a2 != y.a2) {
return false;
}
if (x.arg_count >= 4 && x.a3 != y.a3) {
return false;
}
if (x.arg_count >= 5 && x.a4 != y.a4) {
return false;
}
if (x.arg_count >= 6 && x.a5 != y.a5) {
return false;
}
if (x.arg_count >= 7 && x.a6 != y.a6) {
return false;
}
if (x.arg_count >= 8 && x.a7 != y.a7) {
return false;
}
if (x.arg_count >= 9 && x.a8 != y.a8) {
return false;
}
if (x.arg_count >= 10 && x.a9 != y.a9) {
return false;
}
return true;
if (x.arg_count != y.arg_count) {
return false;
}
if (x.arg_count >= 1 && x.a0 != y.a0) {
return false;
}
if (x.arg_count >= 2 && x.a1 != y.a1) {
return false;
}
if (x.arg_count >= 3 && x.a2 != y.a2) {
return false;
}
if (x.arg_count >= 4 && x.a3 != y.a3) {
return false;
}
if (x.arg_count >= 5 && x.a4 != y.a4) {
return false;
}
if (x.arg_count >= 6 && x.a5 != y.a5) {
return false;
}
if (x.arg_count >= 7 && x.a6 != y.a6) {
return false;
}
if (x.arg_count >= 8 && x.a7 != y.a7) {
return false;
}
if (x.arg_count >= 9 && x.a8 != y.a8) {
return false;
}
if (x.arg_count >= 10 && x.a9 != y.a9) {
return false;
}
return true;
}
private:
emplace_value();
emplace_value(emplace_value const&);
};
};
UNORDERED_AUTO_TEST(emplace_set)
{
UNORDERED_AUTO_TEST (emplace_set) {
test::check_instances check_;
typedef boost::unordered_set<emplace_value, boost::hash<emplace_value> >
container;
container;
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
@@ -233,12 +232,12 @@ UNORDERED_AUTO_TEST(emplace_set)
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 9);
BOOST_TEST(r1.first ==
x.emplace_hint(r1.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r1.first ==
x.emplace_hint(r2.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(
r1.first == x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
r1.first == x.emplace_hint(r1.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(
r1.first == x.emplace_hint(r2.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(
r1.first == x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 12);
@@ -247,15 +246,14 @@ UNORDERED_AUTO_TEST(emplace_set)
BOOST_TEST(x.count(v2) == 1);
BOOST_TEST(x.count(v3) == 1);
BOOST_TEST(x.count(v4) == 1);
}
}
UNORDERED_AUTO_TEST(emplace_multiset)
{
UNORDERED_AUTO_TEST (emplace_multiset) {
test::check_instances check_;
typedef boost::unordered_multiset<emplace_value,
boost::hash<emplace_value> >
container;
boost::hash<emplace_value> >
container;
typedef container::iterator iterator;
container x(10);
iterator i1, i2;
@@ -326,15 +324,14 @@ UNORDERED_AUTO_TEST(emplace_multiset)
BOOST_TEST_EQ(x.count(v1), 1u);
BOOST_TEST_EQ(x.count(v2), 2u);
BOOST_TEST_EQ(x.count(v3), 2u);
}
}
UNORDERED_AUTO_TEST(emplace_map)
{
UNORDERED_AUTO_TEST (emplace_map) {
test::check_instances check_;
typedef boost::unordered_map<emplace_value, emplace_value,
boost::hash<emplace_value> >
container;
boost::hash<emplace_value> >
container;
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
@@ -345,8 +342,8 @@ UNORDERED_AUTO_TEST(emplace_map)
emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
r1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(r1.second);
BOOST_TEST(x.find(k1) == r1.first);
@@ -355,8 +352,8 @@ UNORDERED_AUTO_TEST(emplace_map)
BOOST_TEST_EQ(check_.constructions(), 4);
r2 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(!r2.second);
BOOST_TEST(r1.first == r2.first);
@@ -371,8 +368,8 @@ UNORDERED_AUTO_TEST(emplace_map)
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
emplace_value m2(3, "aaa", 'm');
r1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm'));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm'));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(r1.second);
BOOST_TEST(r1.first->first.arg_count == 9);
@@ -384,29 +381,28 @@ UNORDERED_AUTO_TEST(emplace_map)
BOOST_TEST(r1.first ==
x.emplace_hint(r1.first, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first ==
x.emplace_hint(r2.first, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(r1.first ==
x.emplace_hint(x.end(), boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0')));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 16);
}
}
UNORDERED_AUTO_TEST(emplace_multimap)
{
UNORDERED_AUTO_TEST (emplace_multimap) {
test::check_instances check_;
typedef boost::unordered_multimap<emplace_value, emplace_value,
boost::hash<emplace_value> >
container;
boost::hash<emplace_value> >
container;
typedef container::iterator iterator;
container x(10);
iterator i1, i2, i3, i4;
@@ -416,8 +412,8 @@ UNORDERED_AUTO_TEST(emplace_multimap)
emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
i1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(x.find(k1) == i1);
BOOST_TEST(x.find(k1)->second == m1);
@@ -426,8 +422,8 @@ UNORDERED_AUTO_TEST(emplace_multimap)
emplace_value m1a(8, "xxx", 'z', 4, 5, 6, 7, 8);
i2 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(i1 != i2);
BOOST_TEST(i1->second == m1);
@@ -440,8 +436,8 @@ UNORDERED_AUTO_TEST(emplace_multimap)
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
emplace_value m2(3, "aaa", 'm');
i1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm'));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm'));
BOOST_TEST_EQ(x.size(), 3u);
BOOST_TEST(i1->first.arg_count == 9);
BOOST_TEST(i1->second.arg_count == 3);
@@ -450,24 +446,23 @@ UNORDERED_AUTO_TEST(emplace_multimap)
emplace_value m2a(15, "jkjk");
i2 = x.emplace_hint(i2, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk"));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk"));
emplace_value m2b(275, "xxx", 'm', 6);
i3 = x.emplace_hint(i1, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6));
emplace_value m2c(-10, "blah blah", '\0');
i4 = x.emplace_hint(x.end(), boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0'));
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0'));
BOOST_TEST_EQ(x.size(), 6u);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 20);
BOOST_TEST_EQ(check_.constructions(), 20);
}
}
UNORDERED_AUTO_TEST(try_emplace)
{
UNORDERED_AUTO_TEST (try_emplace) {
test::check_instances check_;
typedef boost::unordered_map<int, emplace_value> container;
@@ -509,11 +504,11 @@ UNORDERED_AUTO_TEST(try_emplace)
BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 808709, "what"));
BOOST_TEST(
r2.first ==
x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10));
r2.first ==
x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r2.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
}
}
}
RUN_TESTS()
+52 -61
View File
@@ -15,8 +15,8 @@
#include "../helpers/test.hpp"
namespace equality_tests {
struct mod_compare
{
struct mod_compare
{
bool alt_hash_;
explicit mod_compare(bool alt_hash = false) : alt_hash_(alt_hash) {}
@@ -25,50 +25,48 @@ struct mod_compare
std::size_t operator()(int x) const
{
return alt_hash_ ? static_cast<std::size_t>(x % 250)
: static_cast<std::size_t>((x + 5) % 250);
return alt_hash_ ? static_cast<std::size_t>(x % 250)
: static_cast<std::size_t>((x + 5) % 250);
}
};
};
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
{ \
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
{ \
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
{ \
boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
{ \
boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
{ \
boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
{ \
boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
{ \
boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, \
map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
{ \
boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
#define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
#define UNORDERED_MAP_INSERT(r, map, item) \
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
UNORDERED_AUTO_TEST(equality_size_tests)
{
UNORDERED_AUTO_TEST (equality_size_tests) {
boost::unordered_set<int> x1, x2;
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
@@ -88,61 +86,54 @@ UNORDERED_AUTO_TEST(equality_size_tests)
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
}
}
UNORDERED_AUTO_TEST(equality_key_value_tests)
{
UNORDERED_AUTO_TEST (equality_key_value_tests) {
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2))
UNORDERED_EQUALITY_SET_TEST((2), ==, (2))
UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1)))
}
}
UNORDERED_AUTO_TEST(equality_collision_test)
{
UNORDERED_AUTO_TEST (equality_collision_test) {
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (501))
UNORDERED_EQUALITY_MULTISET_TEST((1)(251), !=, (1)(501))
UNORDERED_EQUALITY_MULTIMAP_TEST(((251)(1))((1)(1)), !=, ((501)(1))((1)(1)))
UNORDERED_EQUALITY_MULTISET_TEST((1)(501), ==, (1)(501))
UNORDERED_EQUALITY_SET_TEST((1)(501), ==, (501)(1))
}
}
UNORDERED_AUTO_TEST(equality_group_size_test)
{
UNORDERED_AUTO_TEST (equality_group_size_test) {
UNORDERED_EQUALITY_MULTISET_TEST((10)(20)(20), !=, (10)(10)(20))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((10)(1))((20)(1))((20)(1)), !=, ((10)(1))((20)(1))((10)(1)))
((10)(1))((20)(1))((20)(1)), !=, ((10)(1))((20)(1))((10)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((20)(1))((10)(1))((10)(1)), ==, ((10)(1))((20)(1))((10)(1)))
}
((20)(1))((10)(1))((10)(1)), ==, ((10)(1))((20)(1))((10)(1)))
}
UNORDERED_AUTO_TEST(equality_map_value_test)
{
UNORDERED_AUTO_TEST (equality_map_value_test) {
UNORDERED_EQUALITY_MAP_TEST(((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MAP_TEST(((1)(1)), ==, ((1)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
}
}
UNORDERED_AUTO_TEST(equality_predicate_test)
{
UNORDERED_AUTO_TEST (equality_predicate_test) {
UNORDERED_EQUALITY_SET_TEST((1), !=, (1001))
UNORDERED_EQUALITY_MAP_TEST(((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
}
}
UNORDERED_AUTO_TEST(equality_multiple_group_test)
{
UNORDERED_AUTO_TEST (equality_multiple_group_test) {
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1));
}
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1))
}
// Test that equality still works when the two containers have
// different hash functions but the same equality predicate.
// Test that equality still works when the two containers have
// different hash functions but the same equality predicate.
UNORDERED_AUTO_TEST(equality_different_hash_test)
{
UNORDERED_AUTO_TEST (equality_different_hash_test) {
typedef boost::unordered_set<int, mod_compare, mod_compare> set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
@@ -159,7 +150,7 @@ UNORDERED_AUTO_TEST(equality_different_hash_test)
set1.insert(20);
set2.insert(10);
BOOST_TEST(set1 == set2);
}
}
}
RUN_TESTS()
+40 -44
View File
@@ -17,65 +17,61 @@
#include "../helpers/tracker.hpp"
#include "../helpers/invariants.hpp"
#include <iostream>
template <class Container, class Iterator>
void test_equal_insertion(Iterator begin, Iterator end)
{
typedef test::ordered<Container> tracker;
typedef test::ordered<Container> tracker;
Container x1;
tracker x2 = test::create_ordered(x1);
Container x1;
tracker x2 = test::create_ordered(x1);
for (Iterator it = begin; it != end; ++it) {
x1.insert(*it);
x2.insert(*it);
x2.compare_key(x1, *it);
}
for (Iterator it = begin; it != end; ++it) {
x1.insert(*it);
x2.insert(*it);
x2.compare_key(x1, *it);
}
x2.compare(x1);
test::check_equivalent_keys(x1);
x2.compare(x1);
test::check_equivalent_keys(x1);
}
UNORDERED_AUTO_TEST(set_tests)
{
int values[][5] = {{1}, {54, 23}, {-13, 65}, {77, 77}, {986, 25, 986}};
UNORDERED_AUTO_TEST (set_tests) {
int values[][5] = {{1}, {54, 23}, {-13, 65}, {77, 77}, {986, 25, 986}};
typedef boost::unordered_set<int> set;
typedef boost::unordered_multiset<int> multiset;
typedef boost::unordered_set<int> set;
typedef boost::unordered_multiset<int> multiset;
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
test_equal_insertion<set>(values[2], values[2] + 2);
test_equal_insertion<set>(values[3], values[3] + 2);
test_equal_insertion<set>(values[4], values[4] + 3);
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
test_equal_insertion<set>(values[2], values[2] + 2);
test_equal_insertion<set>(values[3], values[3] + 2);
test_equal_insertion<set>(values[4], values[4] + 3);
test_equal_insertion<multiset>(values[0], values[0] + 1);
test_equal_insertion<multiset>(values[1], values[1] + 2);
test_equal_insertion<multiset>(values[2], values[2] + 2);
test_equal_insertion<multiset>(values[3], values[3] + 2);
test_equal_insertion<multiset>(values[4], values[4] + 3);
test_equal_insertion<multiset>(values[0], values[0] + 1);
test_equal_insertion<multiset>(values[1], values[1] + 2);
test_equal_insertion<multiset>(values[2], values[2] + 2);
test_equal_insertion<multiset>(values[3], values[3] + 2);
test_equal_insertion<multiset>(values[4], values[4] + 3);
}
UNORDERED_AUTO_TEST(map_tests)
{
typedef test::list<std::pair<int const, int> > values_type;
values_type v[5];
v[0].push_back(std::pair<int const, int>(1, 1));
v[1].push_back(std::pair<int const, int>(28, 34));
v[1].push_back(std::pair<int const, int>(16, 58));
v[1].push_back(std::pair<int const, int>(-124, 62));
v[2].push_back(std::pair<int const, int>(432, 12));
v[2].push_back(std::pair<int const, int>(9, 13));
v[2].push_back(std::pair<int const, int>(432, 24));
UNORDERED_AUTO_TEST (map_tests) {
typedef test::list<std::pair<int const, int> > values_type;
values_type v[5];
v[0].push_back(std::pair<int const, int>(1, 1));
v[1].push_back(std::pair<int const, int>(28, 34));
v[1].push_back(std::pair<int const, int>(16, 58));
v[1].push_back(std::pair<int const, int>(-124, 62));
v[2].push_back(std::pair<int const, int>(432, 12));
v[2].push_back(std::pair<int const, int>(9, 13));
v[2].push_back(std::pair<int const, int>(432, 24));
for (int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_map<int, int> >(
v[i].begin(), v[i].end());
for (int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_map<int, int> >(
v[i].begin(), v[i].end());
for (int i2 = 0; i2 < 5; ++i2)
test_equal_insertion<boost::unordered_multimap<int, int> >(
v[i2].begin(), v[i2].end());
for (int i2 = 0; i2 < 5; ++i2)
test_equal_insertion<boost::unordered_multimap<int, int> >(
v[i2].begin(), v[i2].end());
}
RUN_TESTS()
+110 -117
View File
@@ -17,7 +17,6 @@
#include "../helpers/invariants.hpp"
#include "../helpers/helpers.hpp"
#include <set>
#include <iostream>
#include <iterator>
#include "../objects/test.hpp"
@@ -28,108 +27,105 @@
struct write_pair_type
{
template <class X1, class X2>
void operator()(std::pair<X1, X2> const& x) const
{
std::cout << "(" << x.first << "," << x.second << ")";
}
template <class X1, class X2>
void operator()(std::pair<X1, X2> const& x) const
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "(" << x.first << "," << x.second << ")";
}
} write_pair;
template <class Container> void write_container(Container const& x)
{
std::for_each(x.begin(), x.end(), write_pair);
std::cout << "\n";
std::for_each(x.begin(), x.end(), write_pair);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
// Make everything collide - for testing erase in a single bucket.
struct collision_hash
{
std::size_t operator()(int) const { return 0; }
std::size_t operator()(int) const { return 0; }
};
// For testing erase in 2 buckets.
struct collision2_hash
{
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x & 1);
}
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x & 1);
}
};
// For testing erase in lots of buckets.
struct collision3_hash
{
std::size_t operator()(int x) const { return static_cast<std::size_t>(x); }
std::size_t operator()(int x) const { return static_cast<std::size_t>(x); }
};
typedef boost::unordered_multimap<int, int, collision_hash, std::equal_to<int>,
test::allocator1<std::pair<int const, int> > >
collide_map;
test::allocator1<std::pair<int const, int> > >
collide_map;
typedef boost::unordered_multimap<int, int, collision2_hash, std::equal_to<int>,
test::allocator2<std::pair<int const, int> > >
collide_map2;
test::allocator2<std::pair<int const, int> > >
collide_map2;
typedef boost::unordered_multimap<int, int, collision3_hash, std::equal_to<int>,
test::allocator2<std::pair<int const, int> > >
collide_map3;
test::allocator2<std::pair<int const, int> > >
collide_map3;
typedef collide_map::value_type collide_value;
typedef test::list<collide_value> collide_list;
UNORDERED_AUTO_TEST(empty_range_tests)
{
collide_map x;
x.erase(x.begin(), x.end());
x.erase(x.begin(), x.begin());
x.erase(x.end(), x.end());
test::check_equivalent_keys(x);
UNORDERED_AUTO_TEST (empty_range_tests) {
collide_map x;
x.erase(x.begin(), x.end());
x.erase(x.begin(), x.begin());
x.erase(x.end(), x.end());
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST(single_item_tests)
{
collide_list init;
init.push_back(collide_value(1, 1));
UNORDERED_AUTO_TEST (single_item_tests) {
collide_list init;
init.push_back(collide_value(1, 1));
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.begin());
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x);
x.erase(x.end(), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x);
x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x);
}
UNORDERED_AUTO_TEST (two_equivalent_item_tests) {
collide_list init;
init.push_back(collide_value(1, 1));
init.push_back(collide_value(1, 2));
{
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.begin());
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x);
x.erase(x.end(), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x);
x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x);
}
}
UNORDERED_AUTO_TEST(two_equivalent_item_tests)
{
collide_list init;
init.push_back(collide_value(1, 1));
init.push_back(collide_value(1, 2));
{
collide_map x(init.begin(), init.end());
int value = test::next(x.begin())->second;
x.erase(x.begin(), test::next(x.begin()));
BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
x.begin()->second == value);
test::check_equivalent_keys(x);
}
{
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x);
}
{
collide_map x(init.begin(), init.end());
int value = test::next(x.begin())->second;
x.erase(x.begin(), test::next(x.begin()));
BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
x.begin()->second == value);
test::check_equivalent_keys(x);
}
{
collide_map x(init.begin(), init.end());
int value = x.begin()->second;
x.erase(test::next(x.begin()), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
x.begin()->second == value);
test::check_equivalent_keys(x);
}
{
collide_map x(init.begin(), init.end());
int value = x.begin()->second;
x.erase(test::next(x.begin()), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
x.begin()->second == value);
test::check_equivalent_keys(x);
}
}
// More automated tests...
@@ -137,88 +133,85 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
template <class Range1, class Range2>
bool compare(Range1 const& x, Range2 const& y)
{
collide_list a(x.begin(), x.end());
collide_list b(y.begin(), y.end());
a.sort();
b.sort();
return a == b;
collide_list a(x.begin(), x.end());
collide_list b(y.begin(), y.end());
a.sort();
b.sort();
return a == b;
}
template <class Container>
bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
{
collide_list l(x.begin(), x.end());
collide_list l(x.begin(), x.end());
l.erase(test::next(l.begin(), start), test::next(l.begin(), end));
x.erase(test::next(x.begin(), start), test::next(x.begin(), end));
l.erase(test::next(l.begin(), start), test::next(l.begin(), end));
x.erase(test::next(x.begin(), start), test::next(x.begin(), end));
test::check_equivalent_keys(x);
return compare(l, x);
test::check_equivalent_keys(x);
return compare(l, x);
}
template <class Container> void erase_subrange_tests(Container const& x)
{
for (std::size_t length = 0; length < x.size(); ++length) {
for (std::size_t position = 0; position < x.size() - length;
++position) {
Container y(x);
collide_list init(y.begin(), y.end());
if (!general_erase_range_test(y, position, position + length)) {
BOOST_ERROR("general_erase_range_test failed.");
std::cout << "Erase: [" << position << "," << position + length
<< ")\n";
write_container(init);
write_container(y);
}
}
for (std::size_t length = 0; length < x.size(); ++length) {
for (std::size_t position = 0; position < x.size() - length; ++position) {
Container y(x);
collide_list init(y.begin(), y.end());
if (!general_erase_range_test(y, position, position + length)) {
BOOST_ERROR("general_erase_range_test failed.");
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase: [" << position << ","
<< position + length << ")\n";
write_container(init);
write_container(y);
}
}
}
}
template <class Container>
void x_by_y_erase_range_tests(Container*, int values, int duplicates)
{
Container y;
Container y;
for (int i = 0; i < values; ++i) {
for (int j = 0; j < duplicates; ++j) {
y.insert(collide_value(i, j));
}
for (int i = 0; i < values; ++i) {
for (int j = 0; j < duplicates; ++j) {
y.insert(collide_value(i, j));
}
}
std::cout << "Values: " << values << ", Duplicates: " << duplicates << "\n";
erase_subrange_tests(y);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Values: " << values
<< ", Duplicates: " << duplicates << "\n";
erase_subrange_tests(y);
}
template <class Container>
void exhaustive_erase_tests(Container* x, int num_values, int num_duplicated)
{
for (int i = 0; i < num_values; ++i) {
for (int j = 0; j < num_duplicated; ++j) {
x_by_y_erase_range_tests(x, i, j);
}
for (int i = 0; i < num_values; ++i) {
for (int j = 0; j < num_duplicated; ++j) {
x_by_y_erase_range_tests(x, i, j);
}
}
}
UNORDERED_AUTO_TEST(exhaustive_collide_tests)
{
std::cout << "exhaustive_collide_tests:\n";
collide_map m;
exhaustive_erase_tests((collide_map*)0, 4, 4);
std::cout << "\n";
UNORDERED_AUTO_TEST (exhaustive_collide_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide_tests:\n";
collide_map m;
exhaustive_erase_tests((collide_map*)0, 4, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
{
std::cout << "exhaustive_collide2_tests:\n";
exhaustive_erase_tests((collide_map2*)0, 8, 4);
std::cout << "\n";
UNORDERED_AUTO_TEST (exhaustive_collide2_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide2_tests:\n";
exhaustive_erase_tests((collide_map2*)0, 8, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
UNORDERED_AUTO_TEST(exhaustive_collide3_tests)
{
std::cout << "exhaustive_collide3_tests:\n";
exhaustive_erase_tests((collide_map3*)0, 8, 4);
std::cout << "\n";
UNORDERED_AUTO_TEST (exhaustive_collide3_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide3_tests:\n";
exhaustive_erase_tests((collide_map3*)0, 8, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
RUN_TESTS()
+200 -207
View File
@@ -18,257 +18,250 @@
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include <vector>
#include <iostream>
#include <cstdlib>
namespace erase_tests {
test::seed_t initialize_seed(85638);
test::seed_t initialize_seed(85638);
template <class Container>
void erase_tests1(Container*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME Container::const_iterator c_iterator;
template <class Container>
void erase_tests1(Container*, test::random_generator generator)
{
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator c_iterator;
std::cerr << "Erase by key.\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
int iterations = 0;
for (BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
it = v.begin();
it != v.end(); ++it) {
std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size();
BOOST_TEST(count == x.erase(test::get_key<Container>(*it)));
BOOST_TEST(x.size() == old_size - count);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
int iterations = 0;
for (typename test::random_values<Container>::iterator it = v.begin();
it != v.end(); ++it) {
std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size();
BOOST_TEST(count == x.erase(test::get_key<Container>(*it)));
BOOST_TEST(x.size() == old_size - count);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
}
std::cerr << "erase(begin()).\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(begin()).\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
iterator pos = x.erase(x.begin());
--size;
BOOST_TEST(pos == x.begin());
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr << "erase(random position).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
std::size_t index = test::random_value(x.size());
c_iterator prev, pos, next;
if (index == 0) {
prev = pos = x.begin();
} else {
prev = test::next(x.begin(), index - 1);
pos = test::next(prev);
}
next = test::next(pos);
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 == 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_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr << "erase(ranges).\n";
{
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
// I'm actually stretching it a little here, as the standard says it
// returns 'the iterator immediately following the erase elements'
// and if nothing is erased, then there's nothing to follow. But I
// think this is the only sensible option...
BOOST_TEST(x.erase(x.end(), x.end()) == x.end());
BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin());
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
typename Container::key_type key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
iterator pos = x.erase(x.begin());
--size;
BOOST_TEST(pos == x.begin());
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
test::check_equivalent_keys(x);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr << "erase(random ranges).\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random position).\n";
{
test::check_instances check_;
Container x;
test::check_instances check_;
for (int i = 0; i < 100; ++i) {
test::random_values<Container> v(1000, generator);
x.insert(v.begin(), v.end());
// Note that erase only invalidates the erased iterators.
std::vector<c_iterator> iterators;
for (c_iterator it = x.cbegin(); it != x.cend(); ++it) {
iterators.push_back(it);
}
iterators.push_back(x.cend());
while (iterators.size() > 1) {
std::size_t start = test::random_value(iterators.size());
std::size_t length =
test::random_value(iterators.size() - start);
x.erase(iterators[start], iterators[start + length]);
iterators.erase(test::next(iterators.begin(), start),
test::next(iterators.begin(), start + length));
BOOST_TEST(x.size() == iterators.size() - 1);
BOOST_DEDUCED_TYPENAME std::vector<c_iterator>::const_iterator
i2 = iterators.begin();
for (c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
BOOST_TEST(i1 == *i2);
++i2;
}
BOOST_TEST(x.cend() == *i2);
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
std::size_t index = test::random_value(x.size());
c_iterator prev, pos, next;
if (index == 0) {
prev = pos = x.begin();
} else {
prev = test::next(x.begin(), index - 1);
pos = test::next(prev);
}
next = test::next(pos);
typename Container::key_type key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
BOOST_TEST(next == x.erase(pos));
--size;
if (size > 0)
BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
<< std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr << "quick_erase(begin()).\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(ranges).\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
// I'm actually stretching it a little here, as the standard says it
// returns 'the iterator immediately following the erase elements'
// and if nothing is erased, then there's nothing to follow. But I
// think this is the only sensible option...
BOOST_TEST(x.erase(x.end(), x.end()) == x.end());
BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin());
BOOST_TEST(x.size() == size);
test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
test::check_equivalent_keys(x);
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random ranges).\n";
{
test::check_instances check_;
Container x;
for (int i = 0; i < 100; ++i) {
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
x.quick_erase(x.begin());
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
x.insert(v.begin(), v.end());
// Note that erase only invalidates the erased iterators.
std::vector<c_iterator> iterators;
for (c_iterator it = x.cbegin(); it != x.cend(); ++it) {
iterators.push_back(it);
}
iterators.push_back(x.cend());
while (iterators.size() > 1) {
std::size_t start = test::random_value(iterators.size());
std::size_t length = test::random_value(iterators.size() - start);
x.erase(iterators[start], iterators[start + length]);
iterators.erase(test::next(iterators.begin(), start),
test::next(iterators.begin(), start + length));
BOOST_TEST(x.size() == iterators.size() - 1);
typename std::vector<c_iterator>::const_iterator i2 =
iterators.begin();
for (c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
BOOST_TEST(i1 == *i2);
++i2;
}
BOOST_TEST(x.cend() == *i2);
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
}
std::cerr << "quick_erase(random position).\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(begin()).\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
std::size_t index = test::random_value(x.size());
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if (index == 0) {
prev = pos = x.begin();
} else {
prev = test::next(x.begin(), index - 1);
pos = test::next(prev);
}
next = test::next(pos);
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 == 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_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
typename Container::key_type key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
x.quick_erase(x.begin());
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(random position).\n";
{
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
std::size_t index = test::random_value(x.size());
typename Container::const_iterator prev, pos, next;
if (index == 0) {
prev = pos = x.begin();
} else {
prev = test::next(x.begin(), index - 1);
pos = test::next(prev);
}
BOOST_TEST(x.empty());
next = test::next(pos);
typename Container::key_type key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
x.quick_erase(pos);
--size;
if (size > 0)
BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
<< std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr << "clear().\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "clear().\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
x.clear();
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
x.clear();
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
}
std::cerr << "\n";
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(
UNORDERED_TEST(
erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
+85 -92
View File
@@ -17,124 +17,117 @@
#include "../helpers/test.hpp"
#include "../helpers/tracker.hpp"
#include "../objects/test.hpp"
#include <boost/next_prior.hpp>
#include <iostream>
namespace extract_tests {
test::seed_t initialize_seed(85638);
test::seed_t initialize_seed(85638);
template <class Container>
void extract_tests1(Container*, test::random_generator generator)
{
std::cerr << "Extract by key.\n";
template <class Container>
void extract_tests1(Container*, test::random_generator generator)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Extract by key.\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
int iterations = 0;
for (BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
it = v.begin();
it != v.end(); ++it) {
std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size();
std::size_t new_count = count ? count - 1 : count;
std::size_t new_size = count ? old_size - 1 : old_size;
typename Container::node_type n =
x.extract(test::get_key<Container>(*it));
BOOST_TEST((n ? true : false) == (count ? true : false));
BOOST_TEST(x.size() == new_size);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == new_count);
if (!new_count) {
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
} else {
BOOST_TEST(x.find(test::get_key<Container>(*it)) != x.end());
}
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
int iterations = 0;
for (typename test::random_values<Container>::iterator it = v.begin();
it != v.end(); ++it) {
std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size();
std::size_t new_count = count ? count - 1 : count;
std::size_t new_size = count ? old_size - 1 : old_size;
typename Container::node_type n =
x.extract(test::get_key<Container>(*it));
BOOST_TEST((n ? true : false) == (count ? true : false));
BOOST_TEST(x.size() == new_size);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == new_count);
if (!new_count) {
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
} else {
BOOST_TEST(x.find(test::get_key<Container>(*it)) != x.end());
}
BOOST_TEST(x.empty());
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr << "extract(begin()).\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(begin()).\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
typename Container::node_type n = x.extract(x.begin());
BOOST_TEST(n);
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
typename Container::key_type key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
typename Container::node_type n = x.extract(x.begin());
BOOST_TEST(n);
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr << "extract(random position).\n";
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(random position).\n";
{
test::check_instances check_;
test::check_instances check_;
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
using namespace std;
int index = rand() % (int)x.size();
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if (index == 0) {
prev = pos = x.begin();
} else {
prev = boost::next(x.begin(), index - 1);
pos = boost::next(prev);
}
next = boost::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
std::size_t count = x.count(key);
typename Container::node_type n = x.extract(pos);
BOOST_TEST(n);
--size;
if (size > 0)
BOOST_TEST(
index == 0 ? next == x.begin() : next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
int iterations = 0;
while (size > 0 && !x.empty()) {
using namespace std;
int index = rand() % (int)x.size();
typename Container::const_iterator prev, pos, next;
if (index == 0) {
prev = pos = x.begin();
} else {
prev = test::next(x.begin(), index - 1);
pos = test::next(prev);
}
BOOST_TEST(x.empty());
next = test::next(pos);
typename Container::key_type key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
typename Container::node_type n = x.extract(pos);
BOOST_TEST(n);
--size;
if (size > 0)
BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
std::cerr << "\n";
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(
UNORDERED_TEST(
extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)))
(default_generator)(generate_collisions)))
}
RUN_TESTS()
+80 -87
View File
@@ -18,109 +18,102 @@
namespace find_tests {
test::seed_t initialize_seed(78937);
test::seed_t initialize_seed(78937);
template <class X> void find_tests1(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
template <class X> void find_tests1(X*, test::random_generator generator)
{
typedef typename X::iterator iterator;
{
test::check_instances check_;
test::check_instances check_;
test::random_values<X> v(500, generator);
X x(v.begin(), v.end());
X const& x_const = x;
test::ordered<X> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end());
test::random_values<X> v(500, generator);
X x(v.begin(), v.end());
X const& x_const = x;
test::ordered<X> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end());
for (BOOST_DEDUCED_TYPENAME test::ordered<X>::const_iterator it1 =
tracker.begin();
it1 != tracker.end(); ++it1) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it1);
BOOST_DEDUCED_TYPENAME X::const_iterator const_pos =
x_const.find(key);
iterator pos = x.find(key);
BOOST_TEST(const_pos != x_const.end());
BOOST_TEST(const_pos != x_const.end() &&
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
BOOST_TEST(pos != x.end());
BOOST_TEST(
pos != x.end() && x.key_eq()(key, test::get_key<X>(*pos)));
for (typename test::ordered<X>::const_iterator it1 = tracker.begin();
it1 != tracker.end(); ++it1) {
typename X::key_type key = test::get_key<X>(*it1);
typename X::const_iterator const_pos = x_const.find(key);
iterator pos = x.find(key);
BOOST_TEST(const_pos != x_const.end());
BOOST_TEST(const_pos != x_const.end() &&
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
BOOST_TEST(pos != x.end());
BOOST_TEST(pos != x.end() && x.key_eq()(key, test::get_key<X>(*pos)));
BOOST_TEST(x.count(key) == tracker.count(key));
BOOST_TEST(x.count(key) == tracker.count(key));
test::compare_pairs(x.equal_range(key), tracker.equal_range(key),
(BOOST_DEDUCED_TYPENAME X::value_type*)0);
test::compare_pairs(x_const.equal_range(key),
tracker.equal_range(key),
(BOOST_DEDUCED_TYPENAME X::value_type*)0);
}
test::compare_pairs(x.equal_range(key), tracker.equal_range(key),
(typename X::value_type*)0);
test::compare_pairs(x_const.equal_range(key), tracker.equal_range(key),
(typename X::value_type*)0);
}
test::random_values<X> v2(500, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it2 =
v2.begin();
it2 != v2.end(); ++it2) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it2);
if (tracker.find(test::get_key<X>(key)) == tracker.end()) {
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x_const.find(key) == x_const.end());
BOOST_TEST(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_TEST(range.first == range.second);
}
test::random_values<X> v2(500, generator);
for (typename test::random_values<X>::const_iterator it2 = v2.begin();
it2 != v2.end(); ++it2) {
typename X::key_type key = test::get_key<X>(*it2);
if (tracker.find(test::get_key<X>(key)) == tracker.end()) {
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x_const.find(key) == x_const.end());
BOOST_TEST(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_TEST(range.first == range.second);
}
}
}
{
test::check_instances check_;
test::check_instances check_;
X x;
X x;
test::random_values<X> v2(5, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it3 =
v2.begin();
it3 != v2.end(); ++it3) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it3);
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_TEST(range.first == range.second);
}
test::random_values<X> v2(5, generator);
for (typename test::random_values<X>::const_iterator it3 = v2.begin();
it3 != v2.end(); ++it3) {
typename X::key_type key = test::get_key<X>(*it3);
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_TEST(range.first == range.second);
}
}
}
}
struct compatible_key
{
struct compatible_key
{
test::object o_;
compatible_key(test::object const& o) : o_(o) {}
};
};
struct compatible_hash
{
struct compatible_hash
{
test::hash hash_;
std::size_t operator()(compatible_key const& k) const
{
return hash_(k.o_);
return hash_(k.o_);
}
};
};
struct compatible_predicate
{
struct compatible_predicate
{
test::equal_to equal_;
bool operator()(compatible_key const& k1, compatible_key const& k2) const
{
return equal_(k1.o_, k2.o_);
return equal_(k1.o_, k2.o_);
}
};
};
template <class X>
void find_compatible_keys_test(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
value_iterator;
template <class X>
void find_compatible_keys_test(X*, test::random_generator generator)
{
typedef typename test::random_values<X>::iterator value_iterator;
test::random_values<X> v(500, generator);
X x(v.begin(), v.end());
@@ -128,37 +121,37 @@ void find_compatible_keys_test(X*, test::random_generator generator)
compatible_predicate eq;
for (value_iterator it = v.begin(), end = v.end(); it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
typename X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
}
test::random_values<X> v2(20, generator);
for (value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
typename X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
}
}
}
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(
UNORDERED_TEST(
find_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(find_compatible_keys_test,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(find_compatible_keys_test,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
+26 -28
View File
@@ -12,41 +12,41 @@
template <typename T>
void call_swap(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
{
swap(x, y);
swap(x, y);
}
template <typename T>
bool call_equals(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
{
return x == y;
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
{
return x != y;
return x != y;
}
template <typename T>
void call_swap(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
{
swap(x, y);
swap(x, y);
}
template <typename T>
bool call_equals(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
{
return x == y;
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
{
return x != y;
return x != y;
}
#include <boost/unordered_map.hpp>
@@ -55,29 +55,27 @@ bool call_not_equals(
typedef boost::unordered_map<int, int> int_map;
typedef boost::unordered_multimap<int, int> int_multimap;
UNORDERED_AUTO_TEST(use_map_fwd_declared_function)
{
int_map x, y;
x[1] = 2;
y[2] = 1;
call_swap(x, y);
UNORDERED_AUTO_TEST (use_map_fwd_declared_function) {
int_map x, y;
x[1] = 2;
y[2] = 1;
call_swap(x, y);
BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
UNORDERED_AUTO_TEST(use_multimap_fwd_declared_function)
{
int_multimap x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
UNORDERED_AUTO_TEST (use_multimap_fwd_declared_function) {
int_multimap x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
}
RUN_TESTS()
+33 -37
View File
@@ -11,55 +11,55 @@
struct true_type
{
char x[100];
char x[100];
};
struct false_type
{
char x;
char x;
};
false_type is_unordered_set_impl(void*);
template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_set<Value, Hash, Pred, Alloc>*);
boost::unordered_set<Value, Hash, Pred, Alloc>*);
template <typename T>
void call_swap(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
{
swap(x, y);
swap(x, y);
}
template <typename T>
bool call_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
{
return x == y;
return x == y;
}
template <typename T>
bool call_not_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
{
return x != y;
return x != y;
}
template <typename T>
void call_swap(boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
{
swap(x, y);
swap(x, y);
}
template <typename T>
bool call_equals(
boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
{
return x == y;
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
{
return x != y;
return x != y;
}
#include "../helpers/test.hpp"
@@ -67,44 +67,40 @@ bool call_not_equals(
typedef boost::unordered_set<int> int_set;
typedef boost::unordered_multiset<int> int_multiset;
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition)
{
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*)0)) == sizeof(true_type));
UNORDERED_AUTO_TEST (use_fwd_declared_trait_without_definition) {
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*)0)) == sizeof(true_type));
}
#include <boost/unordered_set.hpp>
UNORDERED_AUTO_TEST(use_fwd_declared_trait)
{
boost::unordered_set<int> x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
UNORDERED_AUTO_TEST (use_fwd_declared_trait) {
boost::unordered_set<int> x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
}
UNORDERED_AUTO_TEST(use_set_fwd_declared_function)
{
int_set x, y;
x.insert(1);
y.insert(2);
call_swap(x, y);
UNORDERED_AUTO_TEST (use_set_fwd_declared_function) {
int_set x, y;
x.insert(1);
y.insert(2);
call_swap(x, y);
BOOST_TEST(y.find(1) != y.end());
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(y.find(1) != y.end());
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end());
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
UNORDERED_AUTO_TEST(use_multiset_fwd_declared_function)
{
int_multiset x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
UNORDERED_AUTO_TEST (use_multiset_fwd_declared_function) {
int_multiset x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
}
RUN_TESTS()
+95 -90
View File
@@ -13,124 +13,129 @@
#include <utility>
namespace x {
struct D
{
struct D
{
boost::unordered_map<D, D> x;
};
};
}
namespace incomplete_test {
// Declare, but don't define some types.
// Declare, but don't define some types.
struct value;
struct hash;
struct equals;
template <class T> struct allocator;
struct value;
struct hash;
struct equals;
template <class T> struct allocator;
// Declare some instances
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals,
typedef boost::unordered_map<value, value, hash, equals,
allocator<std::pair<value const, value> > >
map;
typedef boost::unordered_multimap<value, value, hash, equals,
typedef boost::unordered_multimap<value, value, hash, equals,
allocator<std::pair<value const, value> > >
multimap;
typedef boost::unordered_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals, allocator<value> >
typedef boost::unordered_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals, allocator<value> >
multiset;
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
struct hash
{
struct hash
{
template <typename T> std::size_t operator()(T const&) const { return 0; }
};
};
struct equals
{
struct equals
{
template <typename T> bool operator()(T const&, T const&) const
{
return true;
return true;
}
};
};
// This is a dubious way to implement an allocator, but good enough
// for this test.
template <typename T> struct allocator : std::allocator<T>
{
// This is a dubious way to implement an allocator, but good enough
// for this test.
template <typename T> struct allocator : std::allocator<T>
{
allocator() {}
template <typename T2>
allocator(const allocator<T2>& other) : std::allocator<T>(other)
{
}
};
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
// moment.
template <typename T2>
allocator(const std::allocator<T2>& other) : std::allocator<T>(other)
{
}
};
struct struct1
{
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
// moment.
struct struct1
{
boost::unordered_map<struct1, struct1, hash, equals,
allocator<std::pair<struct1 const, struct1> > >
x;
};
struct struct2
{
allocator<std::pair<struct1 const, struct1> > >
x;
};
struct struct2
{
boost::unordered_multimap<struct2, struct2, hash, equals,
allocator<std::pair<struct2 const, struct2> > >
x;
};
struct struct3
{
allocator<std::pair<struct2 const, struct2> > >
x;
};
struct struct3
{
boost::unordered_set<struct3, hash, equals, allocator<struct3> > x;
};
struct struct4
{
};
struct struct4
{
boost::unordered_multiset<struct4, hash, equals, allocator<struct4> > x;
};
};
// Now define the value type.
// Now define the value type.
struct value
{
};
struct value
{
};
// Create some instances.
// Create some instances.
incomplete_test::map m1;
incomplete_test::multimap m2;
incomplete_test::set s1;
incomplete_test::multiset s2;
incomplete_test::map m1;
incomplete_test::multimap m2;
incomplete_test::set s1;
incomplete_test::multiset s2;
incomplete_test::struct1 c1;
incomplete_test::struct2 c2;
incomplete_test::struct3 c3;
incomplete_test::struct4 c4;
incomplete_test::struct1 c1;
incomplete_test::struct2 c2;
incomplete_test::struct3 c3;
incomplete_test::struct4 c4;
// Now declare, but don't define, the operators required for comparing
// elements.
// Now declare, but don't define, the operators required for comparing
// elements.
std::size_t hash_value(value const&);
bool operator==(value const&, value const&);
std::size_t hash_value(value const&);
bool operator==(value const&, value const&);
std::size_t hash_value(struct1 const&);
std::size_t hash_value(struct2 const&);
std::size_t hash_value(struct3 const&);
std::size_t hash_value(struct4 const&);
std::size_t hash_value(struct1 const&);
std::size_t hash_value(struct2 const&);
std::size_t hash_value(struct3 const&);
std::size_t hash_value(struct4 const&);
bool operator==(struct1 const&, struct1 const&);
bool operator==(struct2 const&, struct2 const&);
bool operator==(struct3 const&, struct3 const&);
bool operator==(struct4 const&, struct4 const&);
bool operator==(struct1 const&, struct1 const&);
bool operator==(struct2 const&, struct2 const&);
bool operator==(struct3 const&, struct3 const&);
bool operator==(struct4 const&, struct4 const&);
// And finally use these
// And finally use these
void use_types()
{
void use_types()
{
incomplete_test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
@@ -141,28 +146,28 @@ void use_types()
c2.x.insert(std::make_pair(c2, c2));
c3.x.insert(c3);
c4.x.insert(c4);
}
}
// And finally define the operators required for comparing elements.
// And finally define the operators required for comparing elements.
std::size_t hash_value(value const&) { return 0; }
bool operator==(value const&, value const&) { return true; }
std::size_t hash_value(value const&) { return 0; }
bool operator==(value const&, value const&) { return true; }
std::size_t hash_value(struct1 const&) { return 0; }
std::size_t hash_value(struct2 const&) { return 0; }
std::size_t hash_value(struct3 const&) { return 0; }
std::size_t hash_value(struct4 const&) { return 0; }
std::size_t hash_value(struct1 const&) { return 0; }
std::size_t hash_value(struct2 const&) { return 0; }
std::size_t hash_value(struct3 const&) { return 0; }
std::size_t hash_value(struct4 const&) { return 0; }
bool operator==(struct1 const&, struct1 const&) { return true; }
bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; }
bool operator==(struct1 const&, struct1 const&) { return true; }
bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; }
}
int main()
{
// This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring.
// This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring.
incomplete_test::use_types();
incomplete_test::use_types();
}
+34 -42
View File
@@ -15,21 +15,18 @@
#include <map>
#include <set>
#include <iostream>
namespace insert_hint {
UNORDERED_AUTO_TEST(insert_hint_empty)
{
UNORDERED_AUTO_TEST (insert_hint_empty) {
typedef boost::unordered_multiset<int> container;
container x;
x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u);
test::check_equivalent_keys(x);
}
}
UNORDERED_AUTO_TEST(insert_hint_empty2)
{
UNORDERED_AUTO_TEST (insert_hint_empty2) {
typedef boost::unordered_multimap<std::string, int> container;
container x;
x.emplace_hint(x.cbegin(), "hello", 50);
@@ -37,10 +34,9 @@ UNORDERED_AUTO_TEST(insert_hint_empty2)
BOOST_TEST_EQ(x.count("hello"), 1u);
BOOST_TEST_EQ(x.find("hello")->second, 50);
test::check_equivalent_keys(x);
}
}
UNORDERED_AUTO_TEST(insert_hint_single)
{
UNORDERED_AUTO_TEST (insert_hint_single) {
typedef boost::unordered_multiset<std::string> container;
container x;
x.insert("equal");
@@ -48,10 +44,9 @@ UNORDERED_AUTO_TEST(insert_hint_single)
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(x.count("equal"), 2u);
test::check_equivalent_keys(x);
}
}
UNORDERED_AUTO_TEST(insert_hint_single2)
{
UNORDERED_AUTO_TEST (insert_hint_single2) {
typedef boost::unordered_multimap<int, std::string> container;
container x;
x.emplace(10, "one");
@@ -68,47 +63,44 @@ UNORDERED_AUTO_TEST(insert_hint_single2)
BOOST_TEST(v0 != v1);
test::check_equivalent_keys(x);
}
}
UNORDERED_AUTO_TEST(insert_hint_multiple)
{
UNORDERED_AUTO_TEST (insert_hint_multiple) {
for (unsigned int size = 0; size < 10; ++size) {
for (unsigned int offset = 0; offset <= size; ++offset) {
typedef boost::unordered_multiset<std::string> container;
container x;
for (unsigned int offset = 0; offset <= size; ++offset) {
typedef boost::unordered_multiset<std::string> container;
container x;
for (unsigned int i = 0; i < size; ++i) {
x.insert("multiple");
}
BOOST_TEST_EQ(x.size(), size);
container::const_iterator position = x.cbegin();
for (unsigned int i = 0; i < offset; ++i) {
++position;
}
x.insert(position, "multiple");
BOOST_TEST_EQ(x.size(), size + 1u);
BOOST_TEST_EQ(x.count("multiple"), size + 1u);
test::check_equivalent_keys(x);
for (unsigned int i = 0; i < size; ++i) {
x.insert("multiple");
}
}
}
UNORDERED_AUTO_TEST(insert_hint_unique)
{
BOOST_TEST_EQ(x.size(), size);
container::const_iterator position = x.cbegin();
for (unsigned int i = 0; i < offset; ++i) {
++position;
}
x.insert(position, "multiple");
BOOST_TEST_EQ(x.size(), size + 1u);
BOOST_TEST_EQ(x.count("multiple"), size + 1u);
test::check_equivalent_keys(x);
}
}
}
UNORDERED_AUTO_TEST (insert_hint_unique) {
typedef boost::unordered_set<int> container;
container x;
x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u);
test::check_equivalent_keys(x);
}
}
UNORDERED_AUTO_TEST(insert_hint_unique_single)
{
UNORDERED_AUTO_TEST (insert_hint_unique_single) {
typedef boost::unordered_set<int> container;
container x;
x.insert(10);
@@ -123,7 +115,7 @@ UNORDERED_AUTO_TEST(insert_hint_unique_single)
BOOST_TEST_EQ(x.count(10), 1u);
BOOST_TEST_EQ(x.count(20), 1u);
test::check_equivalent_keys(x);
}
}
}
RUN_TESTS()
+13 -13
View File
@@ -9,26 +9,26 @@
int main()
{
#if defined(UNORDERED_TEST_MAP)
typedef boost::unordered_map<int, int> container;
container x;
x.emplace(1, 1);
typedef boost::unordered_map<int, int> container;
container x;
x.emplace(1, 1);
#elif defined(UNORDERED_TEST_MULTIMAP)
typedef boost::unordered_multimap<int, int> container;
container x;
typedef boost::unordered_multimap<int, int> container;
container x;
#elif defined(UNORDERED_TEST_SET)
typedef boost::unordered_set<int> container;
container x;
x.emplace(1);
typedef boost::unordered_set<int> container;
container x;
x.emplace(1);
#elif defined(UNORDERED_TEST_MULTISET)
typedef boost::unordered_multiset<int> container;
container x;
x.emplace(1);
typedef boost::unordered_multiset<int> container;
container x;
x.emplace(1);
#else
#define UNORDERED_ERROR
#endif
#if !defined(UNORDERED_ERROR)
container::node_type n = x.extract(x.begin());
x.insert(n);
container::node_type n = x.extract(x.begin());
x.insert(n);
#endif
}
+11 -13
View File
@@ -12,11 +12,9 @@
#include "../helpers/test.hpp"
#include <iostream>
namespace insert_stable {
struct member
{
struct member
{
int tag1_;
int tag2_;
@@ -25,14 +23,14 @@ struct member
friend bool operator==(member const& x, member const& y)
{
return x.tag1_ == y.tag1_;
return x.tag1_ == y.tag1_;
}
friend bool operator!=(member const& x, member const& y)
{
return x.tag1_ != y.tag1_;
return x.tag1_ != y.tag1_;
}
};
};
}
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
@@ -41,15 +39,15 @@ namespace boost
namespace insert_stable
#endif
{
std::size_t hash_value(insert_stable::member const& x)
{
std::size_t hash_value(insert_stable::member const& x)
{
return static_cast<std::size_t>(x.tag1_);
}
}
}
// 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)
{
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -11,16 +11,16 @@
// clang-format on
void foo(boost::unordered_set<int>&, boost::unordered_map<int, int>&,
boost::unordered_multiset<int>&, boost::unordered_multimap<int, int>&);
boost::unordered_multiset<int>&, boost::unordered_multimap<int, int>&);
int main()
{
boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4;
boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4;
foo(x1, x2, x3, x4);
foo(x1, x2, x3, x4);
return 0;
return 0;
}
+13 -13
View File
@@ -11,20 +11,20 @@
// clang-format on
void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2,
boost::unordered_multiset<int>& x3, boost::unordered_multimap<int, int>& x4)
boost::unordered_multiset<int>& x3, boost::unordered_multimap<int, int>& x4)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy
{
boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4;
};
#if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
struct dummy
{
boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4;
};
#endif
x1.insert(1);
x2[2] = 2;
x3.insert(3);
x4.insert(std::make_pair(4, 5));
x1.insert(1);
x2[2] = 2;
x3.insert(3);
x4.insert(std::make_pair(4, 5));
}
+31 -32
View File
@@ -21,10 +21,10 @@
namespace load_factor_tests {
test::seed_t initialize_seed(783656);
test::seed_t initialize_seed(783656);
template <class X> void set_load_factor_tests(X*)
{
template <class X> void set_load_factor_tests(X*)
{
X x;
BOOST_TEST(x.max_load_factor() == 1.0);
@@ -36,33 +36,32 @@ template <class X> void set_load_factor_tests(X*)
BOOST_TEST(x.max_load_factor() == 2.0);
x.max_load_factor(0.5);
BOOST_TEST(x.max_load_factor() == 0.5);
}
}
template <class X>
void insert_test(X*, float mlf, test::random_generator generator)
{
template <class X>
void insert_test(X*, float mlf, test::random_generator generator)
{
X x;
x.max_load_factor(mlf);
float b = x.max_load_factor();
test::random_values<X> values(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
it = values.begin(),
end = values.end();
for (typename test::random_values<X>::const_iterator it = values.begin(),
end = values.end();
it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(),
old_bucket_count = x.bucket_count();
x.insert(*it);
if (static_cast<double>(old_size + 1) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
typename X::size_type old_size = x.size(),
old_bucket_count = x.bucket_count();
x.insert(*it);
if (static_cast<double>(old_size + 1) <=
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
}
}
template <class X>
void load_factor_insert_tests(X* ptr, test::random_generator generator)
{
template <class X>
void load_factor_insert_tests(X* ptr, test::random_generator generator)
{
insert_test(ptr, 1.0f, generator);
insert_test(ptr, 0.1f, generator);
insert_test(ptr, 100.0f, generator);
@@ -70,24 +69,24 @@ void load_factor_insert_tests(X* ptr, test::random_generator generator)
insert_test(ptr, (std::numeric_limits<float>::min)(), generator);
if (std::numeric_limits<float>::has_infinity)
insert_test(ptr, std::numeric_limits<float>::infinity(), generator);
}
insert_test(ptr, std::numeric_limits<float>::infinity(), generator);
}
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(set_load_factor_tests,
UNORDERED_TEST(set_load_factor_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(load_factor_insert_tests,
UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
+151 -70
View File
@@ -15,12 +15,10 @@
#include "../helpers/test.hpp"
#include "../helpers/tracker.hpp"
#include "../objects/test.hpp"
#include <boost/next_prior.hpp>
namespace merge_tests {
UNORDERED_AUTO_TEST(merge_set)
{
UNORDERED_AUTO_TEST (merge_set) {
boost::unordered_set<int> x;
boost::unordered_set<int> y;
@@ -57,10 +55,9 @@ UNORDERED_AUTO_TEST(merge_set)
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
}
UNORDERED_AUTO_TEST(merge_multiset)
{
UNORDERED_AUTO_TEST (merge_multiset) {
boost::unordered_multiset<int> x;
boost::unordered_multiset<int> y;
@@ -97,11 +94,9 @@ UNORDERED_AUTO_TEST(merge_multiset)
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
}
#if BOOST_UNORDERED_INTEROPERABLE_NODES
UNORDERED_AUTO_TEST(merge_set_and_multiset)
{
UNORDERED_AUTO_TEST (merge_set_and_multiset) {
boost::unordered_set<int> x;
boost::unordered_multiset<int> y;
@@ -138,119 +133,205 @@ 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());
test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2);
}
}
template <class X>
void merge_into_empty_test(X*, test::random_generator generator)
{
template <class X>
void merge_into_empty_test(X*, test::random_generator generator)
{
test::check_instances check_;
test::random_values<X> v(1000, generator);
X x1, 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());
test::check_equivalent_keys(x1);
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);
v1.insert(v2.begin(), boost::next(v2.begin(), 100));
v2.insert(v1.begin(), boost::next(v1.begin(), 100));
test::random_values<X1> v1(1000, generator);
test::random_values<X2> v2(1000, generator);
v1.insert(v2.begin(), test::next(v2.begin(), 100));
v2.insert(v1.begin(), test::next(v1.begin(), 100));
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) {
if (!tracker1.insert(*it).second) {
tracker2.insert(*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);
v1.insert(v2.begin(), boost::next(v2.begin(), 100));
v2.insert(v1.begin(), boost::next(v1.begin(), 100));
test::random_values<X1> v1(1000, generator);
test::random_values<X2> v2(1000, generator);
v1.insert(v2.begin(), test::next(v2.begin(), 100));
v2.insert(v1.begin(), test::next(v1.begin(), 100));
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,
boost::unordered_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_multimap<test::object, test::object, test::hash,
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,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::movable, test::hash, test::equal_to,
test::allocator2<test::movable> >* test_multiset;
boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
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;
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()
+48 -49
View File
@@ -4,90 +4,89 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../objects/test.hpp"
#include <boost/detail/lightweight_test.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/unordered/detail/implementation.hpp>
template <class Tp> struct SimpleAllocator
{
typedef Tp value_type;
typedef Tp value_type;
SimpleAllocator() {}
SimpleAllocator() {}
template <class T> SimpleAllocator(const SimpleAllocator<T>&) {}
template <class T> SimpleAllocator(const SimpleAllocator<T>&) {}
Tp* allocate(std::size_t n)
{
return static_cast<Tp*>(::operator new(n * sizeof(Tp)));
}
Tp* allocate(std::size_t n)
{
return static_cast<Tp*>(::operator new(n * sizeof(Tp)));
}
void deallocate(Tp* p, std::size_t) { ::operator delete((void*)p); }
void deallocate(Tp* p, std::size_t) { ::operator delete((void*)p); }
};
template <typename T> void test_simple_allocator()
{
test::check_instances check_;
test::check_instances check_;
typedef boost::unordered::detail::allocator_traits<SimpleAllocator<T> >
traits;
typedef boost::unordered::detail::allocator_traits<SimpleAllocator<T> >
traits;
BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type,
SimpleAllocator<T> >::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type,
SimpleAllocator<T> >::value));
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::value_type, T>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::value_type, T>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::const_pointer, T const*>::value));
// BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void*
// >::value));
// BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer,
// void const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T*>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::const_pointer, T const*>::value));
// BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void*
// >::value));
// BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer,
// void const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::difference_type,
std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::size_type, std::size_t>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::size_type, std::size_t>::value));
#endif
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value);
// rebind_alloc
// rebind_traits
// rebind_alloc
// rebind_traits
SimpleAllocator<T> a;
SimpleAllocator<T> a;
T* ptr1 = traits::allocate(a, 1);
// T* ptr2 = traits::allocate(a, 1, static_cast<void const*>(ptr1));
T* ptr1 = traits::allocate(a, 1);
// T* ptr2 = traits::allocate(a, 1, static_cast<void const*>(ptr1));
traits::construct(a, ptr1, T(10));
// traits::construct(a, ptr2, T(30), ptr1);
traits::construct(a, ptr1, T(10));
// traits::construct(a, ptr2, T(30), ptr1);
BOOST_TEST(*ptr1 == T(10));
// BOOST_TEST(*ptr2 == T(30));
BOOST_TEST(*ptr1 == T(10));
// BOOST_TEST(*ptr2 == T(30));
traits::destroy(a, ptr1);
// traits::destroy(a, ptr2);
traits::destroy(a, ptr1);
// traits::destroy(a, ptr2);
// traits::deallocate(a, ptr2, 1);
traits::deallocate(a, ptr1, 1);
// traits::deallocate(a, ptr2, 1);
traits::deallocate(a, ptr1, 1);
traits::max_size(a);
traits::max_size(a);
}
int main()
{
test_simple_allocator<int>();
test_simple_allocator<test::object>();
test_simple_allocator<int>();
test_simple_allocator<test::object>();
return boost::report_errors();
return boost::report_errors();
}
+258 -261
View File
@@ -23,353 +23,350 @@
#endif
namespace move_tests {
test::seed_t initialize_seed(98624);
test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
#endif
template <class T> T empty(T*) { return T(); }
template <class T> T empty(T*) { return T(); }
template <class T>
T create(test::random_values<T> const& v, test::object_count& count)
{
template <class T>
T create(test::random_values<T> const& v, test::object_count& count)
{
T x(v.begin(), v.end());
count = test::global_object_count;
return x;
}
}
template <class T>
T create(test::random_values<T> const& v, test::object_count& count,
BOOST_DEDUCED_TYPENAME T::hasher hf, BOOST_DEDUCED_TYPENAME T::key_equal eq,
BOOST_DEDUCED_TYPENAME T::allocator_type al, float mlf)
{
template <class T>
T create(test::random_values<T> const& v, test::object_count& count,
typename T::hasher hf, typename T::key_equal eq,
typename T::allocator_type al, float mlf)
{
T x(0, hf, eq, al);
x.max_load_factor(mlf);
x.insert(v.begin(), v.end());
count = test::global_object_count;
return x;
}
}
template <class T>
void move_construct_tests1(T* ptr, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al;
template <class T>
void move_construct_tests1(T* ptr, test::random_generator const& generator)
{
typename T::hasher hf;
typename T::key_equal eq;
typename T::allocator_type al;
{
test::check_instances check_;
test::check_instances check_;
T y(empty(ptr));
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0);
test::check_equivalent_keys(y);
T y(empty(ptr));
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0);
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::object_count count;
T y(create(v, count));
test::random_values<T> v(1000, generator);
test::object_count count;
T y(create(v, count));
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
test::check_container(y, v);
test::check_equivalent_keys(y);
}
}
}
template <class T>
void move_assign_tests1(T*, test::random_generator const& generator)
{
template <class T>
void move_assign_tests1(T*, test::random_generator const& generator)
{
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(500, generator);
test::object_count count;
T y;
y = create(v, count);
test::random_values<T> v(500, generator);
test::object_count count;
T y;
y = create(v, count);
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
test::check_container(y, v);
test::check_equivalent_keys(y);
}
}
}
template <class T>
void move_construct_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
template <class T>
void move_construct_tests2(T*, test::random_generator const& generator)
{
typename T::hasher hf(1);
typename T::key_equal eq(1);
typename T::allocator_type al(1);
typename T::allocator_type al2(2);
test::object_count count;
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 0.5));
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 0.5));
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
test::check_equivalent_keys(y);
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::check_instances check_;
// TODO: To do this correctly requires the fancy new allocator
// stuff.
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 2.0), al2);
BOOST_TEST(count != test::global_object_count);
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
test::check_equivalent_keys(y);
// TODO: To do this correctly requires the fancy new allocator
// stuff.
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 2.0), al2);
BOOST_TEST(count != test::global_object_count);
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<T> v(25, generator);
T y(create(v, count, hf, eq, al, 1.0), al);
test::random_values<T> v(25, generator);
T y(create(v, count, hf, eq, al, 1.0), al);
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(count == test::global_object_count);
BOOST_TEST(count == test::global_object_count);
#elif defined(BOOST_HAS_NRVO)
BOOST_TEST(
static_cast<std::size_t>(test::global_object_count.constructions -
count.constructions) <=
(test::is_set<T>::value ? 1 : 2) *
(test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances);
BOOST_TEST(
static_cast<std::size_t>(
test::global_object_count.constructions - count.constructions) <=
(test::is_set<T>::value ? 1 : 2) *
(test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances);
#else
BOOST_TEST(
static_cast<std::size_t>(
test::global_object_count.constructions - count.constructions) <=
(test::is_set<T>::value ? 2 : 4) *
(test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
}
template <class T>
void move_assign_tests2(T*, test::random_generator const& generator)
{
typename T::hasher hf(1);
typename T::key_equal eq(1);
typename T::allocator_type al1(1);
typename T::allocator_type al2(2);
typedef typename T::allocator_type allocator_type;
{
test::random_values<T> v(500, generator);
test::random_values<T> v2(0, generator);
T y(v.begin(), v.end(), 0, hf, eq, al1);
test::object_count count;
y = create(v2, count, hf, eq, al2, 2.0);
BOOST_TEST(y.empty());
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 2.0);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::random_values<T> v(500, generator);
test::object_count count;
T y(0, hf, eq, al1);
y = create(v, count, hf, eq, al2, 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
BOOST_TEST(count == test::global_object_count);
}
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(0, hf, eq, al1);
T x(0, hf, eq, al2);
x.max_load_factor(0.25);
x.insert(v.begin(), v.end());
test::object_count count = test::global_object_count;
y = boost::move(x);
if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
BOOST_TEST(count == test::global_object_count);
}
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.25);
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
{
test::check_instances check_;
test::random_values<T> v1(1000, generator);
test::random_values<T> v2(200, generator);
T x(0, hf, eq, al2);
x.max_load_factor(0.5);
x.insert(v2.begin(), v2.end());
test::object_count count1 = test::global_object_count;
T y(v1.begin(), v1.end(), 0, hf, eq, al1);
y = boost::move(x);
test::object_count count2 = test::global_object_count;
if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
BOOST_TEST(count1.instances == test::global_object_count.instances);
BOOST_TEST(
static_cast<std::size_t>(test::global_object_count.constructions -
count.constructions) <=
(test::is_set<T>::value ? 2 : 4) *
(test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
test::check_equivalent_keys(y);
count2.constructions == test::global_object_count.constructions);
}
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
}
}
template <class T>
void move_assign_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al2(2);
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
{
test::random_values<T> v(500, generator);
test::random_values<T> v2(0, generator);
T y(v.begin(), v.end(), 0, hf, eq, al1);
test::object_count count;
y = create(v2, count, hf, eq, al2, 2.0);
BOOST_TEST(y.empty());
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 2.0);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::random_values<T> v(500, generator);
test::object_count count;
T y(0, hf, eq, al1);
y = create(v, count, hf, eq, al2, 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move) {
BOOST_TEST(count == test::global_object_count);
}
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
#endif
}
{
test::check_instances check_;
test::random_values<T> v(500, generator);
T y(0, hf, eq, al1);
T x(0, hf, eq, al2);
x.max_load_factor(0.25);
x.insert(v.begin(), v.end());
test::object_count count = test::global_object_count;
y = boost::move(x);
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move) {
BOOST_TEST(count == test::global_object_count);
}
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.25);
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
{
test::check_instances check_;
test::random_values<T> v1(1000, generator);
test::random_values<T> v2(200, generator);
T x(0, hf, eq, al2);
x.max_load_factor(0.5);
x.insert(v2.begin(), v2.end());
test::object_count count1 = test::global_object_count;
T y(v1.begin(), v1.end(), 0, hf, eq, al1);
y = boost::move(x);
test::object_count count2 = test::global_object_count;
if (BOOST_UNORDERED_TEST_MOVING &&
allocator_type::is_propagate_on_move) {
BOOST_TEST(count1.instances == test::global_object_count.instances);
BOOST_TEST(count2.constructions ==
test::global_object_count.constructions);
}
test::check_container(y, v2);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5);
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
}
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_set_prop_move;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_multiset_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_map_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::propagate_move> >*
test_multimap_prop_move;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_set_no_prop_move;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multiset_no_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_map_no_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multimap_no_prop_move;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(move_construct_tests1,
UNORDERED_TEST(move_construct_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
test_multimap_prop_move)(test_set_no_prop_move)(
test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests1,
test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
test_multimap_prop_move)(test_set_no_prop_move)(
test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
test_multimap_prop_move)(test_set_no_prop_move)(
test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_construct_tests2,
test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
test_multimap_prop_move)(test_set_no_prop_move)(
test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)(
test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
test_set_no_prop_move)(test_multiset_no_prop_move)(
test_map_no_prop_move)(test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests2,
test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)(
test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
test_set_no_prop_move)(test_multiset_no_prop_move)(
test_map_no_prop_move)(test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
+327 -339
View File
@@ -11,426 +11,414 @@
#include "../helpers/helpers.hpp"
#include "../helpers/metafunctions.hpp"
#include "../helpers/test.hpp"
#include <boost/core/pointer_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <set>
#include <string>
UNORDERED_AUTO_TEST(example1)
{
typedef boost::unordered_map<int, std::string>::insert_return_type
insert_return_type;
UNORDERED_AUTO_TEST (example1) {
typedef boost::unordered_map<int, std::string>::insert_return_type
insert_return_type;
boost::unordered_map<int, std::string> src;
src.emplace(1, "one");
src.emplace(2, "two");
src.emplace(3, "buckle my shoe");
boost::unordered_map<int, std::string> dst;
dst.emplace(3, "three");
boost::unordered_map<int, std::string> src;
src.emplace(1, "one");
src.emplace(2, "two");
src.emplace(3, "buckle my shoe");
boost::unordered_map<int, std::string> dst;
dst.emplace(3, "three");
dst.insert(src.extract(src.find(1)));
dst.insert(src.extract(2));
insert_return_type r = dst.insert(src.extract(3));
dst.insert(src.extract(src.find(1)));
dst.insert(src.extract(2));
insert_return_type r = dst.insert(src.extract(3));
BOOST_TEST(src.empty());
BOOST_TEST(dst.size() == 3);
BOOST_TEST(dst[1] == "one");
BOOST_TEST(dst[2] == "two");
BOOST_TEST(dst[3] == "three");
BOOST_TEST(!r.inserted);
BOOST_TEST(r.position == dst.find(3));
BOOST_TEST(r.node.mapped() == "buckle my shoe");
BOOST_TEST(src.empty());
BOOST_TEST(dst.size() == 3);
BOOST_TEST(dst[1] == "one");
BOOST_TEST(dst[2] == "two");
BOOST_TEST(dst[3] == "three");
BOOST_TEST(!r.inserted);
BOOST_TEST(r.position == dst.find(3));
BOOST_TEST(r.node.mapped() == "buckle my shoe");
}
UNORDERED_AUTO_TEST(example2)
{
UNORDERED_AUTO_TEST (example2) {
boost::unordered_set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
// dst.merge(src);
// Merge src into dst.
// src == {5}
// dst == {1, 2, 3, 4, 5}
}
UNORDERED_AUTO_TEST (example3) {
typedef boost::unordered_set<int>::iterator iterator;
boost::unordered_set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
for (iterator i = src.begin(); i != src.end();) {
std::pair<iterator, iterator> p = dst.equal_range(*i);
if (p.first == p.second)
dst.insert(p.first, src.extract(i++));
else
++i;
}
BOOST_TEST(src.size() == 1);
BOOST_TEST(*src.begin() == 5);
std::set<int> dst2(dst.begin(), dst.end());
std::set<int>::iterator it = dst2.begin();
BOOST_TEST(*it++ == 1);
BOOST_TEST(*it++ == 2);
BOOST_TEST(*it++ == 3);
BOOST_TEST(*it++ == 4);
BOOST_TEST(*it++ == 5);
BOOST_TEST(it == dst2.end());
}
UNORDERED_AUTO_TEST (failed_insertion_with_hint) {
{
boost::unordered_set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
// dst.merge(src);
// Merge src into dst.
// src == {5}
// dst == {1, 2, 3, 4, 5}
}
src.emplace(10);
src.emplace(20);
dst.emplace(10);
dst.emplace(20);
UNORDERED_AUTO_TEST(example3)
{
typedef boost::unordered_set<int>::iterator iterator;
boost::unordered_set<int>::node_type nh = src.extract(10);
boost::unordered_set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
for (iterator i = src.begin(); i != src.end();) {
std::pair<iterator, iterator> p = dst.equal_range(*i);
if (p.first == p.second)
dst.insert(p.first, src.extract(i++));
else
++i;
}
BOOST_TEST(src.size() == 1);
BOOST_TEST(*src.begin() == 5);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10);
std::set<int> dst2(dst.begin(), dst.end());
std::set<int>::iterator it = dst2.begin();
BOOST_TEST(*it++ == 1);
BOOST_TEST(*it++ == 2);
BOOST_TEST(*it++ == 3);
BOOST_TEST(*it++ == 4);
BOOST_TEST(*it++ == 5);
BOOST_TEST(it == dst2.end());
}
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10);
UNORDERED_AUTO_TEST(failed_insertion_with_hint)
{
{
boost::unordered_set<int> src;
boost::unordered_set<int> dst;
src.emplace(10);
src.emplace(20);
dst.emplace(10);
dst.emplace(20);
BOOST_TEST(src.count(10) == 0);
BOOST_TEST(src.count(20) == 1);
BOOST_TEST(dst.count(10) == 1);
BOOST_TEST(dst.count(20) == 1);
}
boost::unordered_set<int>::node_type nh = src.extract(10);
{
boost::unordered_map<int, int> src;
boost::unordered_map<int, int> dst;
src.emplace(10, 30);
src.emplace(20, 5);
dst.emplace(10, 20);
dst.emplace(20, 2);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10);
boost::unordered_map<int, int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20);
BOOST_TEST(src.count(10) == 0);
BOOST_TEST(src.count(20) == 1);
BOOST_TEST(dst.count(10) == 1);
BOOST_TEST(dst.count(20) == 1);
}
{
boost::unordered_map<int, int> src;
boost::unordered_map<int, int> dst;
src.emplace(10, 30);
src.emplace(20, 5);
dst.emplace(10, 20);
dst.emplace(20, 2);
boost::unordered_map<int, int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20);
BOOST_TEST(src.count(10) == 0);
BOOST_TEST(src.count(20) == 1);
BOOST_TEST(dst.count(10) == 1);
BOOST_TEST(dst.count(20) == 1);
}
}
template <typename NodeHandle>
bool node_handle_compare(NodeHandle const& nh,
BOOST_DEDUCED_TYPENAME NodeHandle::value_type const& x)
{
return x == nh.value();
BOOST_TEST(src.count(10) == 0);
BOOST_TEST(src.count(20) == 1);
BOOST_TEST(dst.count(10) == 1);
BOOST_TEST(dst.count(20) == 1);
}
}
template <typename NodeHandle>
bool node_handle_compare(
NodeHandle const& nh,
std::pair<BOOST_DEDUCED_TYPENAME NodeHandle::key_type const,
BOOST_DEDUCED_TYPENAME NodeHandle::mapped_type> const& x)
NodeHandle const& nh, typename NodeHandle::value_type const& x)
{
return x.first == nh.key() && x.second == nh.mapped();
return x == nh.value();
}
template <typename NodeHandle>
bool node_handle_compare(
NodeHandle const& nh, std::pair<typename NodeHandle::key_type const,
typename NodeHandle::mapped_type> const& x)
{
return x.first == nh.key() && x.second == nh.mapped();
}
template <typename Container> void node_handle_tests_impl(Container& c)
{
typedef BOOST_DEDUCED_TYPENAME Container::node_type node_type;
typedef typename Container::node_type node_type;
BOOST_DEDUCED_TYPENAME Container::value_type value = *c.begin();
typename Container::value_type value = *c.begin();
node_type n1;
BOOST_TEST(!n1);
BOOST_TEST(n1.empty());
node_type n1;
BOOST_TEST(!n1);
BOOST_TEST(n1.empty());
node_type n2 = c.extract(c.begin());
BOOST_TEST(n2);
BOOST_TEST(!n2.empty());
node_handle_compare(n2, value);
node_type n2 = c.extract(c.begin());
BOOST_TEST(n2);
BOOST_TEST(!n2.empty());
node_handle_compare(n2, value);
node_type n3 = boost::move(n2);
BOOST_TEST(n3);
BOOST_TEST(!n2);
node_handle_compare(n3, value);
// TODO: Check that n2 doesn't have an allocator?
// Maybe by swapping and observing that the allocator is
// swapped rather than moved?
node_type n3 = boost::move(n2);
BOOST_TEST(n3);
BOOST_TEST(!n2);
node_handle_compare(n3, value);
// TODO: Check that n2 doesn't have an allocator?
// Maybe by swapping and observing that the allocator is
// swapped rather than moved?
n1 = boost::move(n3);
BOOST_TEST(n1);
BOOST_TEST(!n3);
node_handle_compare(n1, value);
n1 = boost::move(n3);
BOOST_TEST(n1);
BOOST_TEST(!n3);
node_handle_compare(n1, value);
// Self move-assignment empties the node_handle.
n1 = boost::move(n1);
BOOST_TEST(!n1);
// Self move-assignment empties the node_handle.
n1 = boost::move(n1);
BOOST_TEST(!n1);
n3 = boost::move(n3);
BOOST_TEST(!n3);
n3 = boost::move(n3);
BOOST_TEST(!n3);
BOOST_DEDUCED_TYPENAME Container::value_type value1 = *c.begin();
n1 = c.extract(c.begin());
BOOST_DEDUCED_TYPENAME Container::value_type value2 = *c.begin();
n2 = c.extract(c.begin());
n3 = node_type();
typename Container::value_type value1 = *c.begin();
n1 = c.extract(c.begin());
typename Container::value_type value2 = *c.begin();
n2 = c.extract(c.begin());
n3 = node_type();
node_handle_compare(n1, value1);
node_handle_compare(n2, value2);
n1.swap(n2);
BOOST_TEST(n1);
BOOST_TEST(n2);
node_handle_compare(n1, value2);
node_handle_compare(n2, value1);
node_handle_compare(n1, value1);
node_handle_compare(n2, value2);
n1.swap(n2);
BOOST_TEST(n1);
BOOST_TEST(n2);
node_handle_compare(n1, value2);
node_handle_compare(n2, value1);
BOOST_TEST(n1);
BOOST_TEST(!n3);
n1.swap(n3);
BOOST_TEST(!n1);
BOOST_TEST(n3);
node_handle_compare(n3, value2);
BOOST_TEST(n1);
BOOST_TEST(!n3);
n1.swap(n3);
BOOST_TEST(!n1);
BOOST_TEST(n3);
node_handle_compare(n3, value2);
BOOST_TEST(!n1);
BOOST_TEST(n2);
n1.swap(n2);
BOOST_TEST(n1);
BOOST_TEST(!n2);
node_handle_compare(n1, value1);
BOOST_TEST(!n1);
BOOST_TEST(n2);
n1.swap(n2);
BOOST_TEST(n1);
BOOST_TEST(!n2);
node_handle_compare(n1, value1);
node_type n4;
BOOST_TEST(!n2);
BOOST_TEST(!n4);
n2.swap(n4);
BOOST_TEST(!n2);
BOOST_TEST(!n4);
node_type n4;
BOOST_TEST(!n2);
BOOST_TEST(!n4);
n2.swap(n4);
BOOST_TEST(!n2);
BOOST_TEST(!n4);
}
UNORDERED_AUTO_TEST(node_handle_tests)
{
boost::unordered_set<int> x1;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
node_handle_tests_impl(x1);
UNORDERED_AUTO_TEST (node_handle_tests) {
boost::unordered_set<int> x1;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
node_handle_tests_impl(x1);
boost::unordered_map<int, std::string> x2;
x2.emplace(10, "ten");
x2.emplace(-23, "twenty");
x2.emplace(-76, "thirty");
node_handle_tests_impl(x2);
boost::unordered_map<int, std::string> x2;
x2.emplace(10, "ten");
x2.emplace(-23, "twenty");
x2.emplace(-76, "thirty");
node_handle_tests_impl(x2);
}
template <typename Container1, typename Container2>
void insert_node_handle_unique(Container1& c1, Container2& c2)
{
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
typedef typename Container1::node_type node_type;
typedef typename Container1::value_type value_type;
BOOST_STATIC_ASSERT(
(boost::is_same<node_type, typename Container2::node_type>::value));
typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
insert_return_type1;
typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type
insert_return_type2;
typedef typename Container1::insert_return_type insert_return_type1;
typedef typename Container2::insert_return_type insert_return_type2;
insert_return_type1 r1 = c1.insert(node_type());
insert_return_type2 r2 = c2.insert(node_type());
BOOST_TEST(!r1.inserted);
BOOST_TEST(!r1.node);
BOOST_TEST(r1.position == c1.end());
BOOST_TEST(!r2.inserted);
BOOST_TEST(!r2.node);
BOOST_TEST(r2.position == c2.end());
insert_return_type1 r1 = c1.insert(node_type());
insert_return_type2 r2 = c2.insert(node_type());
BOOST_TEST(!r1.inserted);
BOOST_TEST(!r1.node);
BOOST_TEST(r1.position == c1.end());
BOOST_TEST(!r2.inserted);
BOOST_TEST(!r2.node);
BOOST_TEST(r2.position == c2.end());
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
insert_return_type2 r = c2.insert(c1.extract(c1.begin()));
if (!count) {
BOOST_TEST(r.inserted);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(boost::addressof(*r.position) == v_ptr);
BOOST_TEST(!r.node);
} else {
BOOST_TEST(!r.inserted);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(test::get_key<Container2>(*r.position) ==
test::get_key<Container2>(v));
BOOST_TEST(r.node);
node_handle_compare(r.node, v);
}
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::to_address(c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
insert_return_type2 r = c2.insert(c1.extract(c1.begin()));
if (!count) {
BOOST_TEST(r.inserted);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(boost::to_address(r.position) == v_ptr);
BOOST_TEST(!r.node);
} else {
BOOST_TEST(!r.inserted);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(
test::get_key<Container2>(*r.position) == test::get_key<Container2>(v));
BOOST_TEST(r.node);
node_handle_compare(r.node, v);
}
}
}
template <typename Container1, typename Container2>
void insert_node_handle_unique2(Container1& c1, Container2& c2)
{
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
typedef typename Container1::node_type node_type;
typedef typename Container1::value_type value_type;
BOOST_STATIC_ASSERT(
(boost::is_same<node_type, typename Container2::node_type>::value));
// typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
// insert_return_type1;
typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type
insert_return_type2;
// typedef typename Container1::insert_return_type
// insert_return_type1;
typedef typename Container2::insert_return_type insert_return_type2;
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
insert_return_type2 r =
c2.insert(c1.extract(test::get_key<Container1>(v)));
if (r.inserted) {
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(boost::addressof(*r.position) == v_ptr);
BOOST_TEST(!r.node);
} else {
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(test::get_key<Container2>(*r.position) ==
test::get_key<Container2>(v));
BOOST_TEST(r.node);
node_handle_compare(r.node, v);
}
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::to_address(c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
insert_return_type2 r = c2.insert(c1.extract(test::get_key<Container1>(v)));
if (r.inserted) {
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(boost::to_address(r.position) == v_ptr);
BOOST_TEST(!r.node);
} else {
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
BOOST_TEST(r.position != c2.end());
BOOST_TEST(
test::get_key<Container2>(*r.position) == test::get_key<Container2>(v));
BOOST_TEST(r.node);
node_handle_compare(r.node, v);
}
}
}
template <typename Container1, typename Container2>
void insert_node_handle_equiv(Container1& c1, Container2& c2)
{
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
typedef typename Container1::node_type node_type;
typedef typename Container1::value_type value_type;
BOOST_STATIC_ASSERT(
(boost::is_same<node_type, typename Container2::node_type>::value));
typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1;
typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2;
typedef typename Container1::iterator iterator1;
typedef typename Container2::iterator iterator2;
iterator1 r1 = c1.insert(node_type());
iterator2 r2 = c2.insert(node_type());
BOOST_TEST(r1 == c1.end());
BOOST_TEST(r2 == c2.end());
iterator1 r1 = c1.insert(node_type());
iterator2 r2 = c2.insert(node_type());
BOOST_TEST(r1 == c1.end());
BOOST_TEST(r2 == c2.end());
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
iterator2 r = c2.insert(c1.extract(c1.begin()));
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r != c2.end());
BOOST_TEST(boost::addressof(*r) == v_ptr);
}
while (!c1.empty()) {
value_type v = *c1.begin();
value_type const* v_ptr = boost::to_address(c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v));
iterator2 r = c2.insert(c1.extract(c1.begin()));
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r != c2.end());
BOOST_TEST(boost::to_address(r) == v_ptr);
}
}
struct hash_thing
{
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x * 13 + 5);
}
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x * 13 + 5);
}
};
UNORDERED_AUTO_TEST(insert_node_handle_unique_tests)
{
{
boost::unordered_set<int> x1;
boost::unordered_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 3);
}
UNORDERED_AUTO_TEST (insert_node_handle_unique_tests) {
{
boost::unordered_set<int> x1;
boost::unordered_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_map<int, int, hash_thing> x1;
boost::unordered_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 4);
}
{
boost::unordered_map<int, int, hash_thing> x1;
boost::unordered_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 4);
}
}
UNORDERED_AUTO_TEST(insert_node_handle_equiv_tests)
{
{
boost::unordered_multimap<int, int, hash_thing> x1;
boost::unordered_multimap<int, int> x2;
x1.emplace(67, 50);
x1.emplace(67, 100);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_equiv(x1, x2);
BOOST_TEST(x2.size() == 6);
}
UNORDERED_AUTO_TEST (insert_node_handle_equiv_tests) {
{
boost::unordered_multimap<int, int, hash_thing> x1;
boost::unordered_multimap<int, int> x2;
x1.emplace(67, 50);
x1.emplace(67, 100);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_equiv(x1, x2);
BOOST_TEST(x2.size() == 6);
}
}
UNORDERED_AUTO_TEST(insert_node_handle_unique_tests2)
{
{
boost::unordered_set<int> x1;
boost::unordered_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 3);
}
UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) {
{
boost::unordered_set<int> x1;
boost::unordered_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_map<int, int, hash_thing> x1;
boost::unordered_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 4);
}
{
boost::unordered_map<int, int, hash_thing> x1;
boost::unordered_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 4);
}
}
RUN_TESTS()
+255 -105
View File
@@ -12,159 +12,309 @@
#include "../helpers/test.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
// conditional expression is constant
#pragma warning(disable : 4127)
#endif
namespace noexcept_tests {
// Test the noexcept is set correctly for the move constructor.
// Test the noexcept is set correctly for the move constructor.
struct hash_possible_exception : boost::hash<int>
{
struct hash_possible_exception : boost::hash<int>
{
hash_possible_exception(hash_possible_exception const&) {}
};
struct equal_to_possible_exception : std::equal_to<int>
{
equal_to_possible_exception(equal_to_possible_exception const&) {}
};
// Test that the move constructor does actually move without throwing
// an exception when it claims to.
struct test_exception
{
};
bool throwing_test_exception = false;
void test_throw(char const* name)
{
if (throwing_test_exception) {
std::cerr << "Throw exception in: " << name << std::endl;
throw test_exception();
hash_possible_exception& operator=(hash_possible_exception const&)
{
return *this;
}
}
};
class hash_nothrow_move : boost::hash<int>
{
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
struct equal_to_possible_exception : std::equal_to<int>
{
equal_to_possible_exception(equal_to_possible_exception const&) {}
equal_to_possible_exception& operator=(equal_to_possible_exception const&)
{
return *this;
}
};
// Test that the move constructor does actually move without throwing
// an exception when it claims to.
struct test_exception
{
};
bool throwing_test_exception = false;
void test_throw(char const* name)
{
if (throwing_test_exception) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Throw exception in: " << name
<< std::endl;
throw test_exception();
}
}
template <bool nothrow_move_construct, bool nothrow_move_assign,
bool nothrow_swap>
class hash_nothrow : boost::hash<int>
{
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow)
typedef boost::hash<int> base;
public:
hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move)) BOOST_NOEXCEPT {}
hash_nothrow_move() { test_throw("Constructor"); }
hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); }
hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move))
hash_nothrow(BOOST_RV_REF(hash_nothrow))
BOOST_NOEXCEPT_IF(nothrow_move_construct)
{
test_throw("Assign");
return *this;
if (!nothrow_move_construct) {
test_throw("Move Constructor");
}
}
hash_nothrow_move& operator=(BOOST_RV_REF(hash_nothrow_move))
hash_nothrow() { test_throw("Constructor"); }
hash_nothrow(hash_nothrow const&) { test_throw("Copy"); }
hash_nothrow& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow))
{
test_throw("Assign");
return *this;
}
hash_nothrow& operator=(BOOST_RV_REF(hash_nothrow))
BOOST_NOEXCEPT_IF(nothrow_move_assign)
{
if (!nothrow_move_assign) {
test_throw("Move Assign");
return *this;
}
return *this;
}
std::size_t operator()(int x) const
{
test_throw("Operator");
return static_cast<base const&>(*this)(x);
test_throw("Operator");
return static_cast<base const&>(*this)(x);
}
};
friend void swap(hash_nothrow&, hash_nothrow&)
BOOST_NOEXCEPT_IF(nothrow_swap)
{
if (!nothrow_swap) {
test_throw("Swap");
}
}
};
class equal_to_nothrow_move : std::equal_to<int>
{
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)
typedef hash_nothrow<true, false, false> hash_nothrow_move_construct;
typedef hash_nothrow<false, true, false> hash_nothrow_move_assign;
typedef hash_nothrow<false, false, true> hash_nothrow_swap;
typedef std::equal_to<int> base;
template <bool nothrow_move_construct, bool nothrow_move_assign,
bool nothrow_swap>
class equal_to_nothrow
{
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow)
typedef boost::hash<int> base;
public:
equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move)) BOOST_NOEXCEPT {}
equal_to_nothrow_move() { test_throw("Constructor"); }
equal_to_nothrow_move(equal_to_nothrow_move const&) { test_throw("Copy"); }
equal_to_nothrow_move& operator=(
BOOST_COPY_ASSIGN_REF(equal_to_nothrow_move))
equal_to_nothrow(BOOST_RV_REF(equal_to_nothrow))
BOOST_NOEXCEPT_IF(nothrow_move_construct)
{
test_throw("Assign");
return *this;
if (!nothrow_move_construct) {
test_throw("Move Constructor");
}
}
equal_to_nothrow_move& operator=(BOOST_RV_REF(equal_to_nothrow_move))
equal_to_nothrow() { test_throw("Constructor"); }
equal_to_nothrow(equal_to_nothrow const&) { test_throw("Copy"); }
equal_to_nothrow& operator=(BOOST_COPY_ASSIGN_REF(equal_to_nothrow))
{
test_throw("Assign");
return *this;
}
equal_to_nothrow& operator=(BOOST_RV_REF(equal_to_nothrow))
BOOST_NOEXCEPT_IF(nothrow_move_assign)
{
if (!nothrow_move_assign) {
test_throw("Move Assign");
return *this;
}
return *this;
}
std::size_t operator()(int x, int y) const
{
test_throw("Operator");
return static_cast<base const&>(*this)(x, y);
test_throw("Operator");
return x == y;
}
};
friend void swap(equal_to_nothrow&, equal_to_nothrow&)
BOOST_NOEXCEPT_IF(nothrow_swap)
{
if (!nothrow_swap) {
test_throw("Swap");
}
}
};
bool have_is_nothrow_move = false;
typedef equal_to_nothrow<true, false, false> equal_to_nothrow_move_construct;
typedef equal_to_nothrow<false, true, false> equal_to_nothrow_move_assign;
typedef equal_to_nothrow<false, false, true> equal_to_nothrow_swap;
UNORDERED_AUTO_TEST(check_is_nothrow_move)
{
bool have_is_nothrow_move = false;
bool have_is_nothrow_move_assign = false;
bool have_is_nothrow_swap = false;
UNORDERED_AUTO_TEST (check_is_nothrow_move) {
BOOST_TEST(
!boost::is_nothrow_move_constructible<hash_possible_exception>::value);
!boost::is_nothrow_move_constructible<hash_possible_exception>::value);
BOOST_TEST(
!boost::is_nothrow_move_assignable<hash_possible_exception>::value);
BOOST_TEST(!boost::is_nothrow_swappable<hash_possible_exception>::value);
BOOST_TEST((!boost::is_nothrow_move_constructible<
equal_to_nothrow<false, false, false> >::value));
BOOST_TEST((!boost::is_nothrow_move_assignable<
equal_to_nothrow<false, false, false> >::value));
BOOST_TEST((!boost::is_nothrow_swappable<
equal_to_nothrow<false, false, false> >::value));
have_is_nothrow_move =
boost::is_nothrow_move_constructible<hash_nothrow_move>::value;
boost::is_nothrow_move_constructible<hash_nothrow_move_construct>::value;
have_is_nothrow_move_assign =
boost::is_nothrow_move_assignable<hash_nothrow_move_assign>::value;
have_is_nothrow_swap =
boost::is_nothrow_swappable<hash_nothrow_swap>::value;
// Copied from boost::is_nothrow_move_constructible implementation
// to make sure this does actually detect it when expected.
//
// The type trait is also available when BOOST_IS_NOTHROW_MOVE_CONSTRUCT
// is defined (for some versions of Visual C++?) but detects 'throw()',
// not noexcept.
// Check that the traits work when expected.
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && \
!BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
!BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
BOOST_TEST(have_is_nothrow_move);
BOOST_TEST(have_is_nothrow_move_assign);
#endif
}
UNORDERED_AUTO_TEST(test_noexcept)
{
#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_NOEXCEPT) && \
!defined(BOOST_NO_CXX11_DECLTYPE) && \
!defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
BOOST_TEST(have_is_nothrow_swap);
#endif
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "have_is_nothrow_move: " << have_is_nothrow_move << std::endl
<< "have_is_nothrow_swap: " << have_is_nothrow_swap << std::endl;
}
UNORDERED_AUTO_TEST (test_noexcept) {
if (have_is_nothrow_move) {
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multiset<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multimap<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multiset<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multimap<int, int> >::value));
}
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_set<int, hash_possible_exception> >::value));
BOOST_TEST(
(!boost::is_nothrow_move_constructible<boost::unordered_multiset<int,
boost::hash<int>, equal_to_possible_exception> >::value));
}
(!boost::is_nothrow_move_constructible<boost::unordered_multiset<int,
boost::hash<int>, equal_to_possible_exception> >::value));
}
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
{
typedef boost::unordered_set<int, hash_nothrow_move, equal_to_nothrow_move>
throwing_set;
UNORDERED_AUTO_TEST (test_nothrow_move_when_noexcept) {
typedef boost::unordered_set<int, hash_nothrow_move_construct,
equal_to_nothrow_move_construct>
throwing_set;
if (have_is_nothrow_move) {
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
throwing_test_exception = false;
throwing_set x1;
x1.insert(10);
x1.insert(50);
try {
throwing_test_exception = true;
throwing_set x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
} catch (test_exception) {
BOOST_TEST(false);
}
throwing_test_exception = false;
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
}
throwing_test_exception = false;
throwing_set x1;
x1.insert(10);
x1.insert(50);
try {
throwing_test_exception = true;
throwing_set x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_move);
} catch (test_exception) {
BOOST_TEST(!have_is_nothrow_move);
}
throwing_test_exception = false;
}
UNORDERED_AUTO_TEST (test_nothrow_move_assign_when_noexcept) {
typedef boost::unordered_set<int, hash_nothrow_move_assign,
equal_to_nothrow_move_assign>
throwing_set;
if (have_is_nothrow_move_assign) {
BOOST_TEST(boost::is_nothrow_move_assignable<throwing_set>::value);
}
throwing_test_exception = false;
throwing_set x1;
throwing_set x2;
x1.insert(10);
x1.insert(50);
for (int i = 0; i < 100; ++i) {
x2.insert(i);
}
try {
throwing_test_exception = true;
x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_move_assign);
} catch (test_exception) {
BOOST_TEST(!have_is_nothrow_move_assign);
}
throwing_test_exception = false;
}
UNORDERED_AUTO_TEST (test_nothrow_swap_when_noexcept) {
typedef boost::unordered_set<int, hash_nothrow_swap, equal_to_nothrow_swap>
throwing_set;
if (have_is_nothrow_swap) {
BOOST_TEST(boost::is_nothrow_swappable<throwing_set>::value);
}
throwing_test_exception = false;
throwing_set x1;
throwing_set x2;
x1.insert(10);
x1.insert(50);
for (int i = 0; i < 100; ++i) {
x2.insert(i);
}
try {
throwing_test_exception = true;
x1.swap(x2);
BOOST_TEST(x1.size() == 100);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_swap);
} catch (test_exception) {
BOOST_TEST(!have_is_nothrow_swap);
}
throwing_test_exception = false;
}
}
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
RUN_TESTS()
+89 -90
View File
@@ -18,18 +18,17 @@
namespace rehash_tests {
test::seed_t initialize_seed(2974);
test::seed_t initialize_seed(2974);
template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
{
template <class X> bool postcondition(X const& x, typename X::size_type n)
{
return static_cast<double>(x.bucket_count()) >=
static_cast<double>(x.size()) / x.max_load_factor() &&
static_cast<double>(x.size()) / x.max_load_factor() &&
x.bucket_count() >= n;
}
}
template <class X> void rehash_empty_test1(X*)
{
template <class X> void rehash_empty_test1(X*)
{
X x;
x.rehash(10000);
@@ -40,10 +39,11 @@ template <class X> void rehash_empty_test1(X*)
x.rehash(10000000);
BOOST_TEST(postcondition(x, 10000000));
}
}
template <class X> void rehash_empty_test2(X*, test::random_generator generator)
{
template <class X>
void rehash_empty_test2(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -61,10 +61,11 @@ template <class X> void rehash_empty_test2(X*, test::random_generator generator)
x.rehash(10000000);
tracker.compare(x);
BOOST_TEST(postcondition(x, 10000000));
}
}
template <class X> void rehash_empty_test3(X*, test::random_generator generator)
{
template <class X>
void rehash_empty_test3(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -78,10 +79,10 @@ template <class X> void rehash_empty_test3(X*, test::random_generator generator)
tracker.compare(x);
BOOST_TEST(postcondition(x, 0));
}
}
template <class X> void rehash_test1(X*, test::random_generator generator)
{
template <class X> void rehash_test1(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
@@ -104,10 +105,10 @@ template <class X> void rehash_test1(X*, test::random_generator generator)
x.rehash(1000);
BOOST_TEST(postcondition(x, 1000));
tracker.compare(x);
}
}
template <class X> void reserve_empty_test1(X*)
{
template <class X> void reserve_empty_test1(X*)
{
X x;
x.reserve(10000);
@@ -117,10 +118,10 @@ template <class X> void reserve_empty_test1(X*)
x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 10000000);
}
}
template <class X> void reserve_empty_test2(X*)
{
template <class X> void reserve_empty_test2(X*)
{
X x;
x.max_load_factor(0.25);
@@ -131,100 +132,98 @@ template <class X> void reserve_empty_test2(X*)
x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 40000000);
}
}
template <class X> void reserve_test1(X*, test::random_generator generator)
{
template <class X> void reserve_test1(X*, test::random_generator generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf) {
for (std::size_t i = 1; i < 2000; i += i < 50 ? 1 : 13) {
test::random_values<X> v(i, generator);
for (std::size_t i = 1; i < 2000; i += i < 50 ? 1 : 13) {
test::random_values<X> v(i, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x;
x.max_load_factor(
random_mlf
? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
: 1.0f);
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
X x;
x.max_load_factor(
random_mlf ? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
: 1.0f);
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
// Insert an element before the range insert, otherwise there are
// no iterators to invalidate in the range insert, and it can
// rehash.
typename test::random_values<X>::iterator it = v.begin();
x.insert(*it);
++it;
// Insert an element before the range insert, otherwise there are
// no iterators to invalidate in the range insert, and it can
// rehash.
typename test::random_values<X>::iterator it = v.begin();
x.insert(*it);
++it;
std::size_t bucket_count = x.bucket_count();
x.insert(it, v.end());
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
}
std::size_t bucket_count = x.bucket_count();
x.insert(it, v.end());
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
}
}
}
}
template <class X> void reserve_test2(X*, test::random_generator generator)
{
template <class X> void reserve_test2(X*, test::random_generator generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf) {
for (std::size_t i = 0; i < 2000; i += i < 50 ? 1 : 13) {
test::random_values<X> v(i, generator);
for (std::size_t i = 0; i < 2000; i += i < 50 ? 1 : 13) {
test::random_values<X> v(i, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x;
x.max_load_factor(
random_mlf
? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
: 1.0f);
X x;
x.max_load_factor(
random_mlf ? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
: 1.0f);
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
std::size_t bucket_count = x.bucket_count();
for (typename test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it) {
x.insert(*it);
}
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
std::size_t bucket_count = x.bucket_count();
for (typename test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it) {
x.insert(*it);
}
}
}
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
}
}
}
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset_ptr;
boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
test::allocator2<test::movable> >* test_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(rehash_empty_test1,
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(rehash_empty_test2,
UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_test3,
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_test1,
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_empty_test1,
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(reserve_empty_test2,
UNORDERED_TEST(reserve_empty_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(reserve_test1,
UNORDERED_TEST(reserve_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_test2,
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
+89 -90
View File
@@ -19,117 +19,116 @@
template <class X> void simple_test(X const& a)
{
test::unordered_equivalence_tester<X> equivalent(a);
test::unordered_equivalence_tester<X> equivalent(a);
{
X u;
BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0);
}
{
X u;
BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0);
}
{
BOOST_TEST(equivalent(X(a)));
}
{
BOOST_TEST(equivalent(X(a)));
}
{
X u(a);
BOOST_TEST(equivalent(u));
}
{
X u(a);
BOOST_TEST(equivalent(u));
}
{
X u = a;
BOOST_TEST(equivalent(u));
}
{
X u = a;
BOOST_TEST(equivalent(u));
}
{
X b(a);
BOOST_TEST(b.begin() == const_cast<X const&>(b).cbegin());
BOOST_TEST(b.end() == const_cast<X const&>(b).cend());
}
{
X b(a);
BOOST_TEST(b.begin() == const_cast<X const&>(b).cbegin());
BOOST_TEST(b.end() == const_cast<X const&>(b).cend());
}
{
X b(a);
X c;
BOOST_TEST(equivalent(b));
BOOST_TEST(c.empty());
b.swap(c);
BOOST_TEST(b.empty());
BOOST_TEST(equivalent(c));
b.swap(c);
BOOST_TEST(c.empty());
BOOST_TEST(equivalent(b));
}
{
X b(a);
X c;
BOOST_TEST(equivalent(b));
BOOST_TEST(c.empty());
b.swap(c);
BOOST_TEST(b.empty());
BOOST_TEST(equivalent(c));
b.swap(c);
BOOST_TEST(c.empty());
BOOST_TEST(equivalent(b));
}
{
X u;
X& r = u;
BOOST_TEST(&(r = r) == &r);
{
X u;
X& r = u;
BOOST_TEST(&(r = r) == &r);
BOOST_TEST(r.empty());
BOOST_TEST(&(r = a) == &r);
BOOST_TEST(equivalent(r));
BOOST_TEST(&(r = r) == &r);
BOOST_TEST(equivalent(r));
}
BOOST_TEST(r.empty());
BOOST_TEST(&(r = a) == &r);
BOOST_TEST(equivalent(r));
BOOST_TEST(&(r = r) == &r);
BOOST_TEST(equivalent(r));
}
{
BOOST_TEST(a.size() == static_cast<BOOST_DEDUCED_TYPENAME X::size_type>(
std::distance(a.begin(), a.end())));
}
{
BOOST_TEST(a.size() == static_cast<typename X::size_type>(
std::distance(a.begin(), a.end())));
}
{
BOOST_TEST(a.empty() == (a.size() == 0));
}
{
BOOST_TEST(a.empty() == (a.size() == 0));
}
{
BOOST_TEST(a.empty() == (a.begin() == a.end()));
X u;
BOOST_TEST(u.begin() == u.end());
}
{
BOOST_TEST(a.empty() == (a.begin() == a.end()));
X u;
BOOST_TEST(u.begin() == u.end());
}
}
UNORDERED_AUTO_TEST(simple_tests)
{
using namespace std;
srand(14878);
UNORDERED_AUTO_TEST (simple_tests) {
using namespace std;
srand(14878);
std::cout << "Test unordered_set.\n";
boost::unordered_set<int> set;
simple_test(set);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<int> set;
simple_test(set);
set.insert(1);
set.insert(2);
set.insert(1456);
simple_test(set);
set.insert(1);
set.insert(2);
set.insert(1456);
simple_test(set);
std::cout << "Test unordered_multiset.\n";
boost::unordered_multiset<int> multiset;
simple_test(multiset);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<int> multiset;
simple_test(multiset);
for (int i1 = 0; i1 < 1000; ++i1) {
int count = rand() % 10, index = rand();
for (int j = 0; j < count; ++j)
multiset.insert(index);
}
simple_test(multiset);
for (int i1 = 0; i1 < 1000; ++i1) {
int count = rand() % 10, index = rand();
for (int j = 0; j < count; ++j)
multiset.insert(index);
}
simple_test(multiset);
std::cout << "Test unordered_map.\n";
boost::unordered_map<int, int> map;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<int, int> map;
for (int i2 = 0; i2 < 1000; ++i2) {
map.insert(std::pair<const int, int>(rand(), rand()));
}
simple_test(map);
for (int i2 = 0; i2 < 1000; ++i2) {
map.insert(std::pair<const int, int>(rand(), rand()));
}
simple_test(map);
std::cout << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
for (int i3 = 0; i3 < 1000; ++i3) {
int count = rand() % 10, index = rand();
for (int j = 0; j < count; ++j)
multimap.insert(std::pair<const int, int>(index, rand()));
}
simple_test(multimap);
for (int i3 = 0; i3 < 1000; ++i3) {
int count = rand() % 10, index = rand();
for (int j = 0; j < count; ++j)
multimap.insert(std::pair<const int, int>(index, rand()));
}
simple_test(multimap);
}
RUN_TESTS()
+103 -108
View File
@@ -26,10 +26,10 @@
namespace swap_tests {
test::seed_t initialize_seed(783472);
test::seed_t initialize_seed(783472);
template <class X> void swap_test_impl(X& x1, X& x2)
{
template <class X> void swap_test_impl(X& x1, X& x2)
{
test::ordered<X> tracker1 = test::create_ordered(x1);
test::ordered<X> tracker2 = test::create_ordered(x2);
tracker1.insert_range(x1.begin(), x1.end());
@@ -37,180 +37,175 @@ template <class X> void swap_test_impl(X& x1, X& x2)
x1.swap(x2);
tracker1.compare(x2);
tracker2.compare(x1);
}
}
template <class X> void swap_tests1(X*, test::random_generator generator)
{
template <class X> void swap_tests1(X*, test::random_generator generator)
{
{
test::check_instances check_;
test::check_instances check_;
X x;
swap_test_impl(x, x);
X x;
swap_test_impl(x, x);
}
{
test::check_instances check_;
test::check_instances check_;
X x, y;
swap_test_impl(x, y);
X x, y;
swap_test_impl(x, y);
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<X> v(1000, generator);
X x, y(v.begin(), v.end());
swap_test_impl(x, y);
swap_test_impl(x, y);
test::random_values<X> v(1000, generator);
X x, y(v.begin(), v.end());
swap_test_impl(x, y);
swap_test_impl(x, y);
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<X> vx(1000, generator), vy(1000, generator);
X x(vx.begin(), vx.end()), y(vy.begin(), vy.end());
swap_test_impl(x, y);
swap_test_impl(x, y);
test::random_values<X> vx(1000, generator), vy(1000, generator);
X x(vx.begin(), vx.end()), y(vy.begin(), vy.end());
swap_test_impl(x, y);
swap_test_impl(x, y);
}
}
}
template <class X> void swap_tests2(X* ptr, test::random_generator generator)
{
template <class X> void swap_tests2(X* ptr, test::random_generator generator)
{
swap_tests1(ptr, generator);
typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
typedef typename X::hasher hasher;
typedef typename X::key_equal key_equal;
typedef typename X::allocator_type allocator_type;
{
test::check_instances check_;
test::check_instances check_;
X x(0, hasher(1), key_equal(1));
X y(0, hasher(2), key_equal(2));
swap_test_impl(x, y);
X x(0, hasher(1), key_equal(1));
X y(0, hasher(2), key_equal(2));
swap_test_impl(x, y);
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<X> v(1000, generator);
X x(v.begin(), v.end(), 0, hasher(1), key_equal(1));
X y(0, hasher(2), key_equal(2));
swap_test_impl(x, y);
test::random_values<X> v(1000, generator);
X x(v.begin(), v.end(), 0, hasher(1), key_equal(1));
X y(0, hasher(2), key_equal(2));
swap_test_impl(x, y);
}
{
test::check_instances check_;
test::check_instances check_;
test::random_values<X> vx(100, generator), vy(50, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2));
test::random_values<X> vx(100, generator), vy(50, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2));
swap_test_impl(x, y);
swap_test_impl(x, y);
}
{
test::force_equal_allocator force_(!allocator_type::is_propagate_on_swap);
test::check_instances check_;
test::random_values<X> vx(50, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator()) {
swap_test_impl(x, y);
}
}
{
test::force_equal_allocator force_(!allocator_type::is_propagate_on_swap);
test::check_instances check_;
test::random_values<X> vx(100, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1), allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2), allocator_type(2));
if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator()) {
swap_test_impl(x, y);
swap_test_impl(x, y);
}
}
}
{
test::force_equal_allocator force_(
!allocator_type::is_propagate_on_swap);
test::check_instances check_;
test::random_values<X> vx(50, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator()) {
swap_test_impl(x, y);
}
}
{
test::force_equal_allocator force_(
!allocator_type::is_propagate_on_swap);
test::check_instances check_;
test::random_values<X> vx(100, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1),
allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2),
allocator_type(2));
if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator()) {
swap_test_impl(x, y);
swap_test_impl(x, y);
}
}
}
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_set_prop_swap;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_multiset_prop_swap;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_map_prop_swap;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::propagate_swap> >*
test_multimap_prop_swap;
boost::unordered_set<test::object, test::hash, test::equal_to,
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_set_no_prop_swap;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_multiset_no_prop_swap;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_map_no_prop_swap;
boost::unordered_multimap<test::object, test::object, test::hash,
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_multimap_no_prop_swap;
template <typename T> bool is_propagate(T*)
{
template <typename T> bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_swap;
}
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_AUTO_TEST(check_traits)
{
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_swap));
BOOST_TEST(!is_propagate(test_set_no_prop_swap));
}
}
UNORDERED_TEST(swap_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)(
test_multimap_prop_swap)(test_set_no_prop_swap)(
test_multiset_no_prop_swap)(test_map_no_prop_swap)(
test_multimap_no_prop_swap))(
UNORDERED_TEST(
swap_tests1, ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(
test_multimap)(test_set_prop_swap)(test_multiset_prop_swap)(
test_map_prop_swap)(test_multimap_prop_swap)(
test_set_no_prop_swap)(test_multiset_no_prop_swap)(
test_map_no_prop_swap)(test_multimap_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(swap_tests2,
UNORDERED_TEST(swap_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_swap)(
test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)(
test_set_no_prop_swap)(test_multiset_no_prop_swap)(
test_map_no_prop_swap)(test_multimap_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range)))
test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)(
test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(
test_multimap_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range)))
}
RUN_TESTS()
+175 -135
View File
@@ -10,12 +10,11 @@
#include "../helpers/postfix.hpp"
// clang-format on
#include <iostream>
#include "../helpers/test.hpp"
namespace unnecessary_copy_tests {
struct count_copies
{
struct count_copies
{
private:
BOOST_COPYABLE_AND_MOVABLE(count_copies)
public:
@@ -25,14 +24,14 @@ struct count_copies
count_copies() : tag_(0), id_(++id_count)
{
++copies;
trace_op("Default construct");
++copies;
trace_op("Default construct");
}
explicit count_copies(int tag) : tag_(tag), id_(++id_count)
{
++copies;
trace_op("Tag construct");
++copies;
trace_op("Tag construct");
}
// This bizarre constructor is an attempt to confuse emplace.
@@ -47,66 +46,66 @@ struct count_copies
count_copies(count_copies const&, count_copies const& x)
: tag_(x.tag_), id_(++id_count)
{
++copies;
trace_op("Pair construct");
++copies;
trace_op("Pair construct");
}
count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count)
{
++copies;
trace_op("Copy construct");
++copies;
trace_op("Copy construct");
}
count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_), id_(++id_count)
{
x.tag_ = -1;
++moves;
trace_op("Move construct");
x.tag_ = -1;
++moves;
trace_op("Move construct");
}
count_copies& operator=(
BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
{
tag_ = p.tag_;
++copies;
trace_op("Copy assign");
return *this;
tag_ = p.tag_;
++copies;
trace_op("Copy assign");
return *this;
}
count_copies& operator=(BOOST_RV_REF(count_copies) p) // Move assignment
{
tag_ = p.tag_;
++moves;
trace_op("Move assign");
return *this;
tag_ = p.tag_;
++moves;
trace_op("Move assign");
return *this;
}
~count_copies() { trace_op("Destruct"); }
void trace_op(char const* str)
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_ << " (#" << id_
<< ")" << std::endl;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_ << " (#" << id_
<< ")" << std::endl;
}
int tag_;
int id_;
};
};
bool operator==(count_copies const& x, count_copies const& y)
{
bool operator==(count_copies const& x, count_copies const& y)
{
return x.tag_ == y.tag_;
}
}
template <class T> T source() { return T(); }
template <class T> T source() { return T(); }
void reset()
{
void reset()
{
count_copies::copies = 0;
count_copies::moves = 0;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\nReset\n" << std::endl;
}
}
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
@@ -115,10 +114,10 @@ namespace boost
namespace unnecessary_copy_tests
#endif
{
std::size_t hash_value(unnecessary_copy_tests::count_copies const& x)
{
std::size_t hash_value(unnecessary_copy_tests::count_copies const& x)
{
return static_cast<std::size_t>(x.tag_);
}
}
}
// Boost.Move doesn't seem to work very well on this compiler.
@@ -136,107 +135,159 @@ std::size_t hash_value(unnecessary_copy_tests::count_copies const& x)
#endif
#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; \
}
if (::unnecessary_copy_tests::count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies << " expecting: " << n \
<< std::endl; \
}
#define MOVE_COUNT(n) \
if (::unnecessary_copy_tests::count_copies::moves != n) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr << "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::moves \
<< " expecting: " << n << std::endl; \
}
if (::unnecessary_copy_tests::count_copies::moves != n) { \
BOOST_ERROR("Wrong number of moves."); \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Number of moves: " << ::unnecessary_copy_tests::count_copies::moves \
<< " expecting: " << n << std::endl; \
}
#define COPY_COUNT_RANGE(a, b) \
if (::unnecessary_copy_tests::count_copies::copies < a || \
::unnecessary_copy_tests::count_copies::copies > b) { \
BOOST_ERROR("Wrong number of copies."); \
std::cerr << "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
if (::unnecessary_copy_tests::count_copies::copies < a || \
::unnecessary_copy_tests::count_copies::copies > b) { \
BOOST_ERROR("Wrong number of copies."); \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies << " expecting: [" \
<< a << ", " << b << "]" << std::endl; \
}
#define MOVE_COUNT_RANGE(a, b) \
if (::unnecessary_copy_tests::count_copies::moves < a || \
::unnecessary_copy_tests::count_copies::moves > b) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr << "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::moves \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
if (::unnecessary_copy_tests::count_copies::moves < a || \
::unnecessary_copy_tests::count_copies::moves > b) { \
BOOST_ERROR("Wrong number of moves."); \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Number of moves: " << ::unnecessary_copy_tests::count_copies::moves \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
#define COPY_COUNT_EXTRA(a, b) COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
#define MOVE_COUNT_EXTRA(a, b) MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
namespace unnecessary_copy_tests {
int count_copies::copies;
int count_copies::moves;
int count_copies::id_count;
int count_copies::copies;
int count_copies::moves;
int count_copies::id_count;
template <class T> void unnecessary_copy_insert_test(T*)
{
template <class T> void unnecessary_copy_insert_test(T*)
{
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
typename T::value_type a;
reset();
x.insert(a);
COPY_COUNT(1);
}
MOVE_COUNT(0);
}
boost::unordered_set<count_copies>* set;
boost::unordered_multiset<count_copies>* multiset;
boost::unordered_map<int, count_copies>* map;
boost::unordered_multimap<int, count_copies>* multimap;
template <class T> void unnecessary_copy_insert_rvalue_set_test(T*)
{
T x;
typename T::value_type a;
reset();
x.insert(boost::move(a));
COPY_COUNT(0);
MOVE_COUNT(1);
UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap)))
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_emplace_test(T*)
{
template <class T> void unnecessary_copy_insert_rvalue_map_test(T*)
{
// Doesn't currently try to emulate std::pair move construction,
// so std::pair's require a copy. Could try emulating it in
// construct_from_args.
T x;
typename T::value_type a;
reset();
x.insert(boost::move(a));
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1);
MOVE_COUNT(0);
#else
COPY_COUNT(0);
MOVE_COUNT(1);
#endif
typename T::value_type a2;
reset();
x.insert(boost::move(a));
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT((x.size() == 2 ? 1 : 0));
MOVE_COUNT(0);
#else
COPY_COUNT(0);
MOVE_COUNT((x.size() == 2 ? 1 : 0));
#endif
}
boost::unordered_set<count_copies>* set;
boost::unordered_multiset<count_copies>* multiset;
boost::unordered_map<int, count_copies>* map;
boost::unordered_multimap<int, count_copies>* multimap;
UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap)))
UNORDERED_TEST(unnecessary_copy_insert_rvalue_set_test, ((set)(multiset)))
UNORDERED_TEST(unnecessary_copy_insert_rvalue_map_test, ((map)(multimap)))
template <class T> void unnecessary_copy_emplace_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
typename T::value_type a;
COPY_COUNT(1);
x.emplace(a);
COPY_COUNT(2);
}
}
template <class T> void unnecessary_copy_emplace_rvalue_test(T*)
{
template <class T> void unnecessary_copy_emplace_rvalue_test(T*)
{
reset();
T x;
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
x.emplace(source<typename T::value_type>());
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1);
#else
COPY_COUNT(2);
#endif
}
}
UNORDERED_TEST(unnecessary_copy_emplace_test, ((set)(multiset)(map)(multimap)))
UNORDERED_TEST(
UNORDERED_TEST(
unnecessary_copy_emplace_test, ((set)(multiset)(map)(multimap)))
UNORDERED_TEST(
unnecessary_copy_emplace_rvalue_test, ((set)(multiset)(map)(multimap)))
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T> void unnecessary_copy_emplace_std_move_test(T*)
{
template <class T> void unnecessary_copy_emplace_std_move_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
typename T::value_type a;
COPY_COUNT(1);
MOVE_COUNT(0);
x.emplace(std::move(a));
COPY_COUNT(1);
MOVE_COUNT(1);
}
}
UNORDERED_TEST(
UNORDERED_TEST(
unnecessary_copy_emplace_std_move_test, ((set)(multiset)(map)(multimap)))
#endif
template <class T> void unnecessary_copy_emplace_boost_move_test(T*)
{
template <class T> void unnecessary_copy_emplace_boost_move_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
typename T::value_type a;
COPY_COUNT(1);
MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a));
@@ -248,32 +299,33 @@ template <class T> void unnecessary_copy_emplace_boost_move_test(T*)
COPY_COUNT_RANGE(1, 2);
MOVE_COUNT_RANGE(0, 1);
#endif
}
}
UNORDERED_TEST(
UNORDERED_TEST(
unnecessary_copy_emplace_boost_move_test, ((set)(multiset)(map)(multimap)))
template <class T> void unnecessary_copy_emplace_boost_move_set_test(T*)
{
template <class T> void unnecessary_copy_emplace_boost_move_set_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
typename T::value_type a;
COPY_COUNT(1);
MOVE_COUNT(0);
x.emplace(boost::move(a));
COPY_COUNT(1);
MOVE_COUNT(1);
}
}
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_set_test, ((set)(multiset)))
UNORDERED_TEST(
unnecessary_copy_emplace_boost_move_set_test, ((set)(multiset)))
template <class T> void unnecessary_copy_emplace_boost_move_map_test(T*)
{
template <class T> void unnecessary_copy_emplace_boost_move_map_test(T*)
{
reset();
T x;
COPY_COUNT(0);
MOVE_COUNT(0);
BOOST_DEDUCED_TYPENAME T::value_type a;
typename T::value_type a;
COPY_COUNT(1);
MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a));
@@ -284,12 +336,12 @@ template <class T> void unnecessary_copy_emplace_boost_move_map_test(T*)
COPY_COUNT(1);
MOVE_COUNT(1);
#endif
}
}
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_map_test, ((map)(multimap)))
UNORDERED_TEST(
unnecessary_copy_emplace_boost_move_map_test, ((map)(multimap)))
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
{
UNORDERED_AUTO_TEST (unnecessary_copy_emplace_set_test) {
// When calling 'source' the object is moved on some compilers, but not
// others. So count that here to adjust later.
@@ -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;
@@ -380,10 +422,9 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
x.emplace(b, b);
COPY_COUNT(1);
MOVE_COUNT(0);
}
}
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
{
UNORDERED_AUTO_TEST (unnecessary_copy_emplace_map_test) {
// When calling 'source' the object is moved on some compilers, but not
// others. So count that here to adjust later.
@@ -409,7 +450,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();
@@ -429,7 +470,7 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
reset();
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
boost::make_tuple());
boost::make_tuple());
COPY_COUNT(2);
MOVE_COUNT(0);
@@ -450,7 +491,7 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
MOVE_COUNT(source_pair_cost);
#if !(defined(__GNUC__) && __cplusplus < 199900L) && \
!(defined(_MSC_VER) && _MSC_VER < 1600)
!(defined(_MSC_VER) && _MSC_VER < 1600)
count_copies part;
reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
@@ -496,17 +537,16 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
reset();
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(boost::ref(b.first)),
boost::make_tuple(boost::ref(b.second)));
boost::make_tuple(boost::ref(b.first)),
boost::make_tuple(boost::ref(b.second)));
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,
std::make_tuple(std::ref(b.first)),
std::make_tuple(std::ref(b.second)));
std::make_tuple(std::ref(b.first)), std::make_tuple(std::ref(b.second)));
COPY_COUNT(0);
MOVE_COUNT(0);
@@ -520,23 +560,23 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
std::pair<count_copies const, count_copies> move_source;
reset();
x.emplace(boost::unordered::piecewise_construct,
std::make_tuple(std::move(move_source.first)),
std::make_tuple(std::move(move_source.second)));
std::make_tuple(std::move(move_source.first)),
std::make_tuple(std::move(move_source.second)));
COPY_COUNT(tuple_copy_cost);
MOVE_COUNT(tuple_move_cost);
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
reset();
x.emplace(boost::unordered::piecewise_construct,
std::forward_as_tuple(b.first), std::forward_as_tuple(b.second));
std::forward_as_tuple(b.first), std::forward_as_tuple(b.second));
COPY_COUNT(0);
MOVE_COUNT(0);
#endif
#endif
}
}
}
RUN_TESTS()