Compare commits

...

546 Commits

Author SHA1 Message Date
Daniel James 84dd473a5d Merge remote-tracking branch 'origin/develop' 2015-02-22 15:12:28 +00:00
Daniel James f014802eb6 Release note for pull request #4. 2015-02-22 15:08:46 +00:00
Daniel James 68eb654e7a Merge pull request #4 from tempoz/patch-2
Bounds-check after arithmetic is complete
2014-12-09 01:04:30 +00:00
Zoey Greer 3a507b4e39 Bounds-check after arithmetic is complete
double_to_size can return std::numeric_limits<size_t>max(), so we cannot add 1 to the return value of double_to_size. That addition should be done while still working with a double, as can be seen being done on line 850 of this file.
This was uncovered by Coverity, and addresses Coverity issues CID13443 and CID12664
2014-12-08 16:38:38 -05:00
Daniel James 0273ec59d7 Fix Visual C++ 9.0 workaround. 2014-12-03 18:28:40 +00:00
Daniel James 9090d87725 Restore ampersand workaround for Visual C++ 9 2014-11-16 10:01:29 +00:00
Daniel James 8ccde2e5a1 Move the allocators after copying the hash functions.
Just in case the hash functions throw.
2014-11-09 23:44:16 +00:00
Daniel James 31211a607f Remove assertion that used moved allocator. Fixes #10777. 2014-11-09 23:35:35 +00:00
Daniel James 56ab93d296 Merge pull request #3 from awulkiew/fix/iterators
Remove template patameters from friend declarations in interator.
2014-11-09 15:14:02 +00:00
Adam Wulkiewicz 1d8855da27 Remove template patameters from friend declarations in interator<>. 2014-11-09 13:36:27 +01:00
Daniel James df5a7538b1 Changelog 2014-11-08 22:22:12 +00:00
Daniel James 0cedaf7ad6 Rename iterator typedef to n_iterator. 2014-11-08 22:22:11 +00:00
Daniel James b4795f414d Remove unneeded ConstNodePointer template parameters. 2014-11-08 22:22:11 +00:00
Daniel James 2c9d209eef Remove incorrect changelog note.
A minor change that is not actually in this release, will be in the next one.
Probably too late to rebuild the documenation.
2014-11-02 17:35:05 +00:00
Daniel James a81c86a90e Remove use of operator&.
Also reactivate operator& for minimal test classes. Apparently I
disabled them because of a problem in a type trait, but I'm not seeing
that now. Maybe it will appear on other compilers.
2014-10-26 22:21:12 +00:00
Daniel James bf0f90ff03 Merge branch 'develop' 2014-10-26 12:18:38 +00:00
Daniel James 7c6f1ef227 Changelog 2014-10-26 12:17:58 +00:00
Daniel James 99985bb1b2 Fix pointer types in iterators.
https://svn.boost.org/trac/boost/ticket/10672
2014-10-22 22:03:32 +01:00
Zoey Greer 8c5aa5086d Initialize data_ in value_base default constructor
This means data_ should get initialized in the default constructor for boost::unordered::detail::unique_node (and any other inheritors), as this constructor will be called there.

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

This reverts commits: 2f6b81d8c1 and
e1b39bbbfb.
2014-10-22 21:24:36 +01:00
Daniel James 2f6b81d8c1 Rename iterator typedef to n_iterator. 2014-08-19 16:41:10 +01:00
Daniel James e1b39bbbfb Combine some of the headers. 2014-08-19 16:41:10 +01:00
Daniel James 6b7cecb9d3 Workaround initialiser list bug in gcc 4.4. 2014-08-02 03:11:44 +01:00
Daniel James 79dcf7cbe8 Merge branch 'develop' 2014-07-28 23:33:28 +01:00
Daniel James d4702754b7 The correct release notes.
The ones I entered were for hash.
2014-07-27 18:01:00 +01:00
Daniel James 98d90f26d7 Merge branch 'develop' 2014-07-27 12:20:58 +01:00
Daniel James b97ceb6442 Release notes. 2014-07-27 12:20:56 +01:00
Daniel James c18c645b92 Merge remote-tracking branch 'origin/develop' 2014-07-27 11:59:55 +01:00
Daniel James 15cb6d7d1b Tweak warning flags in tests. 2014-07-14 21:49:58 +01:00
Daniel James 2f5d98a0cd Don't use allocator to construct/destroy anything other than elements.
As specified in 23.2.1.3.
2014-07-12 19:12:46 +01:00
Daniel James 2216c987a0 Fixed direct use of allocator. 2014-07-11 09:13:47 +01:00
Daniel James 86d4d21250 Make value_base a member of pointer nodes. 2014-07-11 08:40:07 +01:00
Daniel James 3eb2355182 Merge branch 'develop' 2014-06-30 10:43:47 +01:00
Daniel James 9440395330 Fix swap link. 2014-06-16 22:45:04 +01:00
Daniel James 034f2c3779 Update metadata. 2014-06-16 22:43:54 +01:00
Daniel James e93f5b0971 Update link to swap. 2014-06-08 15:33:40 +01:00
Daniel James 8c6f3e910b Merge branch 'develop' 2014-03-25 22:05:25 +00:00
Daniel James 78bd2c0736 Fix map allocators in introduction. Fixes trac #9719. 2014-03-11 03:48:26 +00:00
Daniel James 4e6ce91dd0 Regenerate libraries.json with latest script. 2014-02-27 22:46:07 +00:00
Daniel James 850d69738b Switch to latest meta/libraries.json 2014-02-27 22:30:01 +00:00
Daniel James 9c62f83e74 Add maintainers to metadata. 2014-02-24 22:22:09 +00:00
Daniel James 99fdce0b4d Fix policy typedefs. 2014-02-24 16:54:12 +00:00
Daniel James 06b6418044 Add metadata 2014-02-23 14:30:21 +00:00
Daniel James 57819d1dd9 Always use prime policy for integers. Fixes trac #9282. 2014-02-23 10:16:14 +00:00
Daniel James 80f3376894 Merge branch 'develop' - clean up warnings. 2014-02-11 08:10:13 +00:00
Daniel James 94071cc6e8 Clean up warnings. Fixes trac #9377. 2014-01-26 22:57:24 +00:00
Daniel James 038550a9df Fix some issues tests, and git tweak.
Merge branch 'develop'
2014-01-26 15:40:01 +00:00
Daniel James 9ca8c691ac Ignore html build files. 2014-01-26 13:44:38 +00:00
Daniel James a4881436d2 Disable forward_as_tuple test for older Visual C++. 2014-01-23 22:49:05 +00:00
Daniel James 70190b3aa2 Disable test for compilers that emulate old Visual C++. 2014-01-15 00:04:13 +00:00
Daniel James 8ae166a2c3 Tweak compiler checks in unnecessary_copy_tests.
I'm running these tests by default now, which will probably break
several compilers, so I'll need to add extra conditions later.
2014-01-15 00:00:01 +00:00
Daniel James 7d0c6d2425 Unused typedef. 2013-12-15 17:11:26 +00:00
Daniel James 5995e5521f Account for extra moves/copies when using Visual Age. 2013-12-15 17:11:26 +00:00
Daniel James 59c83ab942 Reintroduce std::move test.
There used to be a std::move test here, but it was changed to
boost::test for a wider range of testing, but I'd quite like to test
with std::move regardless.
2013-12-15 17:11:25 +00:00
Daniel James 0a552a47cb Disable test for Visual C++ 12. 2013-12-15 17:11:25 +00:00
Daniel James 3b5cf359e7 Merge branch 'master' into develop
Using 'ours' strategy, so nothing actually changed.
2013-12-07 19:10:39 +00:00
Daniel James 239453bead Fix unordered on Sun 5.12 compiler. Refs #9424.
[SVN r86792]
2013-11-23 11:43:19 +00:00
Daniel James bea92e8842 Merge unordered and hash from trunk.
- Only use Visual C++ pragma with appropriate compilers.
- Working link for Thomas Wang's hash function.
- Updated unordered rationale.
- Fix `unnecessary_copy_tests` for Visual C++ 12.
- Some extra insert tests.


[SVN r86728]
2013-11-16 20:36:27 +00:00
Daniel James ddab816ed7 Use BOOST_HAS_PRAGMA_ONCE.
Remembering to first include config, so that it'll actually be defined.

[SVN r86726]
2013-11-16 20:13:24 +00:00
Daniel James 007ddb9a5a Update the unordered rationale.
I just noticed that it wan't updated for the changes on 64 bit platforms.
Not very good, but I don't want to spend too long on this.  I'm tempted to just
delete it.

[SVN r86608]
2013-11-10 23:26:21 +00:00
Daniel James 6b1a4bfeb7 Link to archived copy of Thomas Wang's integer hash function.
His site's no longer on the web, so use web.archive.org instead.

[SVN r86607]
2013-11-10 23:25:54 +00:00
Daniel James 6ca8d5e0d9 Merge Visual C++ 12 fix for Unordered.
[SVN r86551]
2013-11-03 19:20:09 +00:00
Daniel James 6f3dee13a8 Extend the Visual C++ workaround to 3 parameters.
To avoid collision with piecewise construction.

[SVN r86506]
2013-10-28 20:32:52 +00:00
Daniel James 7f14796ba4 Try to work around Visual C++'s variadic overload bug.
Possibly too late for the release.

[SVN r86482]
2013-10-27 17:58:09 +00:00
Daniel James cfb4a9d254 Revert attempted work around for Visual C++.
[SVN r86478]
2013-10-27 13:14:12 +00:00
Daniel James 621c1523c0 Fix potential msvc 12 workaround.
[SVN r86433]
2013-10-25 22:21:51 +00:00
Daniel James b4d62e4670 Attempt to work around Visual C++ initializer list overload bug.
I'm hoping that these templated initializer lists will be considered a better
overload than the others. I have no idea if it will actually work, this is a
real shot in the dark.

The enable_if checks should probably be for implicit conversion, there might
be a chance this could override a valid call when there's an explicit
conversion.

[SVN r86419]
2013-10-24 18:11:35 +00:00
Daniel James 3922d1bb63 This special case doesn't seem to apply to the latest Visual C++.
[SVN r86365]
2013-10-19 16:53:37 +00:00
Daniel James 9b9a1d21a6 Merge release notes + float hash fix. Ref #8822.
[SVN r86210]
2013-10-08 21:26:30 +00:00
Daniel James 033a611f71 Change log.
[SVN r86173]
2013-10-06 08:03:12 +00:00
Stephen Kelly 3aa91346ea Remove obsolete MSVC check from pragma guard
git grep -h -B1 "^#\s*pragma once" | grep -v pragma | sort | uniq

is now clean.

[SVN r85952]
2013-09-26 13:02:51 +00:00
Daniel James a7c0ddb5b3 Merge unordered to release. Fixes #8851, #8874
Avoid some warnings, and move detail functions into a sub-namespace to avoid
exposing them via. ADL.


[SVN r85388]
2013-08-18 09:44:14 +00:00
Daniel James de0366105c Avoid Visual C++ warning.
Avoiding:

    warning C4127: conditional expression is constant

[SVN r85281]
2013-08-10 13:09:28 +00:00
Daniel James 3508ceaa58 Avoid exposing functions via ADL.
I'd put the iterators in their own namespace so that they wouldn't pick
up functions in detail via ADL, but I forgot that their template
parameters would cause that to happen anyway. The simplest way to fix
that for now is just to stuff the problematic functions into a
sub-namespace, so that they're no longer exposed.

[SVN r85280]
2013-08-10 13:09:08 +00:00
Daniel James 29660f9c4d Remove unused typedef. Refs #8874.
[SVN r85245]
2013-08-08 20:28:53 +00:00
Daniel James 52b42b4e48 Fix unused variable warning. Refs #8851.
Bit annoying that `boost::ignore_unused_variable_warning` is in
`<boost/concept_check.hpp>`.

[SVN r85244]
2013-08-08 20:27:40 +00:00
Daniel James c88126e1d2 Merge unordered from trunk.
Add `BOOST_NOEXPECT` to:

- Move constructors (when appropriate)
- Destructors
- Iterators

Also, fix some misleading documentation about the containers' move support.


[SVN r85048]
2013-07-15 21:32:45 +00:00
Daniel James e6a6fe92d7 Fix misleading documentation about move support.
[SVN r84985]
2013-07-08 22:11:54 +00:00
Daniel James 0c7c7cc6ad Merge some change log entries to release.
[SVN r84497]
2013-05-25 15:53:49 +00:00
Daniel James fb93c8cb86 Change log entries for 1.54.0
[SVN r84496]
2013-05-25 15:45:51 +00:00
Daniel James 8f0126a13a Revert siphash example.
Since I'm not going to release it.


[SVN r84434]
2013-05-22 21:48:29 +00:00
Daniel James 0f080552fa Remove 'private' definition that I used for debugging.
[SVN r84408]
2013-05-21 22:50:19 +00:00
Daniel James f8a6ea40a1 Add noexcept annotations to iterators.
I couldn't find any sepecification in the standard, but I'd assume that since
`begin` and `end` are both `noexcept`, the iterator copy constructors must be.

To justify adding `noexcept` to these members, see 17.6.3.5 (part of the
allocator requirements) of n3485, which says about allocator's pointer types,
"No constructor, comparison operator, copy operation, move operation, or swap
operation on these types shall exit via an exception."

Not relevant in this case but allocator pointers also need to model
NullablePointer. From 17.6.3.3, "No operation which is part of the
NullablePointer requirements shall exit via an exception."

[SVN r84374]
2013-05-19 15:00:40 +00:00
Daniel James 1a067034c1 Add conditional noexcept for move constructors.
Also added `noexcept` for destructors because of a gcc bug, see:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56191

Found via:

http://stackoverflow.com/questions/15721544/destructors-and-noexcept

[SVN r84373]
2013-05-19 14:30:12 +00:00
Daniel James bd10a8b5aa Merge initial unordered use of noexcept + friends.
Still more to come, hopefully in time for the release.


[SVN r84304]
2013-05-16 22:15:42 +00:00
Daniel James d603e75d03 Use nothrow move construction for function objects, when available.
[SVN r84277]
2013-05-13 23:13:04 +00:00
Daniel James a422b40041 Use nothrow move assignment for function objects, when available.
Originally I was going to use two different versions of `hash_functions`, but
the recent discussion on binary compatibility persuaded me not to.

[SVN r84276]
2013-05-13 23:12:46 +00:00
Daniel James 44f61e5878 Add BOOST_NOEXCEPT to unordered container methods.
I haven't done the iterators yet.

[SVN r84253]
2013-05-12 14:34:45 +00:00
Daniel James 27c4e90374 Add trailing newlines to siphash examples.
I'm not sure if I'll actually release this example. I don't think it does a
good job of demonstrating what I wanted.

[SVN r84249]
2013-05-12 14:33:15 +00:00
Daniel James 0221f1a9bd Unordered: Merge assign fix.
[SVN r82651]
2013-01-27 23:10:29 +00:00
Daniel James 6b21eeccab Unordered: Fix move assignment with unequal allocators.
[SVN r82614]
2013-01-25 21:22:03 +00:00
Daniel James bf1f24ab04 Unordered: Initial stab at siphash example.
[SVN r81973]
2012-12-15 16:42:44 +00:00
Daniel James 34b69e67ee Unordered: Merge test tweaks + inspect fixes from trunk.
[SVN r81922]
2012-12-13 22:39:44 +00:00
Daniel James 64994d76dd Unordered: Detab.
[SVN r81762]
2012-12-07 17:06:11 +00:00
Daniel James 10049f8325 Unordered: Missing final newlines.
[SVN r81761]
2012-12-07 17:05:36 +00:00
Daniel James 654fed166a Unordered: Remove and update various deprecated things.
[SVN r81727]
2012-12-05 22:06:57 +00:00
Marshall Clow 1bd3b029fa Removed usage of deprecated macros
[SVN r81563]
2012-11-26 17:47:12 +00:00
Daniel James 3305caf40c Unordered: Changelog notes.
[SVN r81474]
2012-11-22 08:59:27 +00:00
Marshall Clow 85d2657ac1 Remove usage of deprecated macros
[SVN r81449]
2012-11-21 01:21:54 +00:00
Daniel James 8fb85cbb8d Unordered: Fix overload edge case for piecewise construction.
[SVN r81393]
2012-11-17 12:03:55 +00:00
Daniel James da455124d2 Unordered: Try to make the piecewise_construct emulation a little more readable.
[SVN r81392]
2012-11-17 12:03:32 +00:00
Daniel James ef4d33ce89 Unordered: Remove the deprecated equality implementation.
[SVN r81385]
2012-11-17 10:30:19 +00:00
Daniel James 7eefe62efe Unordered: Remove deprecated variadic pair constructors.
This was emulating them as specified in older standard drafts.

[SVN r81384]
2012-11-17 10:28:35 +00:00
Daniel James 981f1e2acb Unordered: Merge code clean up.
[SVN r81358]
2012-11-15 13:43:37 +00:00
Daniel James 73c0d85ae6 Unorderd: Stop deriving from hash policy.
[SVN r81209]
2012-11-05 18:33:29 +00:00
Daniel James d495cbd7e6 Unordered: Clean up the pointer silliness.
[SVN r81208]
2012-11-05 18:33:15 +00:00
Daniel James ccc3d1c83d Unordered: Simpler erase implementation.
[SVN r81207]
2012-11-05 18:32:59 +00:00
Daniel James 38d8d052d1 Unordered: Simplify pointer use.
[SVN r81206]
2012-11-05 18:32:45 +00:00
Daniel James 2e26534659 Unordered: Improved exception test thing.
Allows repetition of exception tests + separate running the tests so that
different tests types or configurations can be mixed up.

[SVN r81030]
2012-10-21 00:20:07 +00:00
Daniel James d1a6e948e3 Unordered: bcp friendly macros.
[SVN r81029]
2012-10-21 00:17:40 +00:00
Daniel James 81897a6469 Unordered: Fix erasing ranges, and some tests. Fixes #7471
[SVN r80958]
2012-10-11 17:29:19 +00:00
Daniel James 8f8ea09ce8 Unordered: Fix bug when erasing a range, refs #7471.
[SVN r80894]
2012-10-07 08:19:01 +00:00
Daniel James ced2139eea Unordered/Hash: Merge change log.
[SVN r80778]
2012-09-30 11:58:06 +00:00
Daniel James 9b398ba0c9 Unordered: Update change log.
[SVN r80776]
2012-09-30 11:55:58 +00:00
Daniel James 556adc1de1 Unordered: Fix the Visual C++ 11 version number.
[SVN r80768]
2012-09-30 08:29:26 +00:00
Daniel James 3f060a70d1 Unordered: Fix unnecessary_copy_tests + extra tests.
It looks the odd result in unnecessary_copy_tests on Visual C++ 11 is not a
bug, but add some extra tests just to make sure. Also some extra rehash and
reserve testing thrown in.

[SVN r80705]
2012-09-26 08:09:26 +00:00
Daniel James d6322718f3 Unordered: A bit more feedback from unnecessary_copy_tests
[SVN r80635]
2012-09-22 18:32:22 +00:00
Daniel James 0a8037243b Unordered: Merge slightly simpler implementation.
[SVN r80632]
2012-09-22 17:28:55 +00:00
Daniel James 94ef1ac391 Unordered: Support empty containers in node_holder.
[SVN r80562]
2012-09-17 18:59:29 +00:00
Daniel James 53f278312f Unordered: Get rid of get_start.
[SVN r80561]
2012-09-17 18:59:03 +00:00
Daniel James 549b93e629 Unordered: delete_buckets works when buckets_ is null.
[SVN r80560]
2012-09-17 18:58:28 +00:00
Daniel James c2e7221bf9 Unordered: Set max_load_ to 0 when there are no buckets.
[SVN r80559]
2012-09-17 18:57:58 +00:00
Daniel James a0ceefc91a Unordered: Merge from trunk.
Faster assign, plus simplified some of the implementation.


[SVN r80558]
2012-09-17 18:53:30 +00:00
Daniel James 37d58e84e3 Unordered: Fix creating extra node when resizing.
[SVN r80518]
2012-09-13 19:50:31 +00:00
Daniel James ec6219fe13 Unordered: Fix incorrect assertion.
[SVN r80508]
2012-09-12 21:09:39 +00:00
Daniel James 05f7c37f54 Unordered: Merge tests to release
[SVN r80435]
2012-09-07 19:51:10 +00:00
Daniel James e68f0c341e Unordered: Fix object counts in tests.
[SVN r80417]
2012-09-06 08:49:43 +00:00
Daniel James f47f0f8d16 Unordered: Fix some issues with the tests.
[SVN r80416]
2012-09-05 23:33:22 +00:00
Daniel James ed369d6374 Unordered: Move MSVC warning suppression to correct location.
[SVN r80412]
2012-09-05 19:02:29 +00:00
Daniel James b6b54610c6 Unordered: Repeat assign tests several times.
[SVN r80411]
2012-09-05 19:02:04 +00:00
Daniel James 1d03bbe213 Unordered: Re-initialise reused nodes.
[SVN r80410]
2012-09-05 19:01:17 +00:00
Daniel James 32ab636fe8 Unordered: delete/destroy/clear cleanup.
[SVN r80390]
2012-09-03 20:06:00 +00:00
Daniel James 8e5ffbbe6c Unordered: Clean up swap.
[SVN r80389]
2012-09-03 20:05:39 +00:00
Daniel James e7f495c094 Unordered: Cleaning up a bit.
[SVN r80388]
2012-09-03 20:05:15 +00:00
Daniel James 1e07edc1ad Unordered: No need for value_allocator.
[SVN r80387]
2012-09-03 20:04:55 +00:00
Daniel James 2f09079d3f Unordered: Remove the now unnecessary uses of ->.
[SVN r80386]
2012-09-03 20:04:35 +00:00
Daniel James a1bdd82bd5 Unordered: Get rid of buckets.
[SVN r80385]
2012-09-03 20:04:15 +00:00
Daniel James 45b6340a98 Unordered: Avoid allocating nodes in table constructor.
[SVN r80384]
2012-09-03 20:03:55 +00:00
Daniel James 22e6daac6c Unordered: Use node_holder for move.
[SVN r80383]
2012-09-03 20:03:35 +00:00
Daniel James 9ea735c975 Unordered: Move iterators to top of buckets.hpp
[SVN r80382]
2012-09-03 20:03:15 +00:00
Daniel James 31f3a10d33 Unordered: Tweak node_construct functions.
[SVN r80381]
2012-09-03 20:02:53 +00:00
Daniel James d9f49f2b44 Unordered: Faster assign implementation
[SVN r80380]
2012-09-03 20:02:31 +00:00
Daniel James 73c269398a Unordered: Generic copy/move implementation.
[SVN r80379]
2012-09-03 20:02:10 +00:00
Daniel James 7a4930f1a1 Unordered: Avoid unnecessary swapping in rehash and move.
[SVN r80378]
2012-09-03 20:01:50 +00:00
Daniel James d5971171da Unordered: Merge from trunk.
- Some changes to the internals, including reverting some of the
  recent changes to constructing values which turned out to be
  more bother than it was worth.
- On C++11 compilers, better use of `construct` and `destroy`.
- Better testing.


[SVN r80350]
2012-09-01 15:50:36 +00:00
Daniel James 035396e89f Unordered: Merge reference documentation update.
[SVN r80294]
2012-08-28 21:56:18 +00:00
Daniel James c0faf59a86 Unordered: De-template constructor for allocator2 from allocator.
Sun is failing one of the tests because it isn't using it implicitly.


[SVN r80276]
2012-08-28 08:04:51 +00:00
Daniel James a822b27efc Unordered: Weaken requirements in compile tests.
Assigning a container requires that its elements can be assignable. Could split
the tests up so that other tests aren't assignable, but it doesn't seem worth
the hassle.

[SVN r80228]
2012-08-25 21:56:16 +00:00
Daniel James f1e716d897 Unordered: Stronger assign testing.
[SVN r80227]
2012-08-25 21:55:46 +00:00
Daniel James 612d68eecd Unordered: More invariant testing.
In case there are elements in buckets that aren't in the element list. Required
because the data structure has changed since the original implementation.

[SVN r80226]
2012-08-25 21:55:18 +00:00
Daniel James aefea862c2 Unordered: Two exception testing allocators.
For different C++11 properties.

[SVN r80225]
2012-08-25 21:54:50 +00:00
Daniel James f8968ab022 Unordered: Better swap assertion.
[SVN r80224]
2012-08-25 21:54:18 +00:00
Daniel James 8f86c2464e Unordered: Rename *_impl to *_value_impl.
To make it clear that they should only be used to construct and destroy
the value, and not nodes or buckets.

[SVN r80223]
2012-08-25 21:53:53 +00:00
Daniel James cd57bf5000 Unordered: And use allocator traits to destroy values.
[SVN r80222]
2012-08-25 21:53:25 +00:00
Daniel James a7125259d8 Unordered: When full construct is available, use it for value.
[SVN r80221]
2012-08-25 21:52:57 +00:00
Daniel James 3a163b5449 Unordered: Move some things around.
- Move `allocator_traits` before `construct_impl` so the
  `construct_impl` can be changed to use `allocator_traits`.
- Moved some move utilities out of `allocate.hpp` because they're
  really nothing to do with allocation and construction.

[SVN r80220]
2012-08-25 21:52:28 +00:00
Daniel James ff31c73970 Unordered: Go back to the old method for constructing nodes.
Reverts much of [78349]. Keeps the variadic construct.

[SVN r80219]
2012-08-25 21:51:24 +00:00
Daniel James 2e11fd8a86 Unordered: Test number of copies and moves for moves on all compilers.
Mainly because I want to get more info on the odd test failure for Visual C++
11. I expect that with move emulation these results could vary considerably,
and since I've only tested with gcc and clang so far, it's quite likely that
this test will now fail for other compilers.

[SVN r80200]
2012-08-25 12:52:31 +00:00
Daniel James 09c546f63a Unordered: Document more fine grained requirements.
[SVN r79879]
2012-08-05 18:26:02 +00:00
Daniel James 8683332b2c Unordered: Merge from trunk
- Avoid an incorrect MSVC unused variable warning in the tests.
- Remove a `try..catch`.
- Adjust SFINAE use to try to supprt g++ 3.4. Fixes #7175.
- Fix some use of rvalues.
- Extra info in `at_tests`.



[SVN r79868]
2012-08-05 08:34:44 +00:00
Daniel James 5be71a0e90 Unordered: Output stages in at_tests.
Getting a memory deallocation error from Sandia's linux c++11 clang. Add some
trace output to see if it gives a clue where it's going wrong.

[SVN r79793]
2012-07-29 07:18:35 +00:00
Daniel James 27f5496a65 Unordered: Fix some uses of rvalues refs/move.
[SVN r79792]
2012-07-29 07:17:57 +00:00
Daniel James 918b3da91d Unordered: Use a SFINAE parameter rather than return type for C++03 compilers.
Seems that g++ 3.4 has problems with overloads that are only distinguished by
SFINAE return types.

[SVN r79762]
2012-07-26 22:23:09 +00:00
Daniel James 61516be1db Unordered: Remove use of try..catch.
So that it'll work when exceptions are disabled.

[SVN r79679]
2012-07-22 20:14:20 +00:00
Daniel James 7c968fd38d Unordered: Avoid an MSVC warning.
[SVN r79651]
2012-07-22 07:14:42 +00:00
Daniel James d77453b7ad Unordered: Merge allocator fix + improved tests. Fixes #7100.
[SVN r79547]
2012-07-15 23:58:02 +00:00
Daniel James cf9930fe20 Unordered: Merge updated c++11 config macros.
[SVN r79546]
2012-07-15 23:47:12 +00:00
Daniel James e30a99d2fc Unordered: Merge some of the older changes from trunk.
Code reorganization, simpler tests, better use of Boost.Move.


[SVN r79545]
2012-07-15 23:44:41 +00:00
Daniel James 4a066e4b18 Unordered: Fix unnecessary_copy_tests for MSVC10
Compilers with rvalue references can avoid creating a node, as they can use the
value from the rvalue reference to check if the value is already in the
container (in this case it is) before creating the node. Could possibly do the
same for compilers without rvalue references, if it can get a value out of
Boost.Move's rvalue reference emulation.

[SVN r79503]
2012-07-14 16:45:54 +00:00
Marshall Clow 0fccd93e29 Switch from deprecated macros to new shiny ones; no functionality change
[SVN r79396]
2012-07-09 22:08:01 +00:00
Daniel James 6932a2d571 Unordered: Fix using a C++03 allocator with C++11 compiler.
Because the nodes had an implicit constructor, the `has_construct` traits was
detecting that the nodes could be constructed by construction then copy, which
really wasn't wanted. Also add a check that nodes aren't been copy constructed
to make sure this doesn't happen again. Refs #7100.

[SVN r79358]
2012-07-08 11:55:57 +00:00
Daniel James f387994422 Unordered: Test with more allocators.
Causes some C++11 failures....

[SVN r79357]
2012-07-08 11:55:35 +00:00
Daniel James 958b1d468f Unordered: Reduce the amount of meta-stuff in the tests.
Some of this was there for older compilers, some is just premature
generalization. There's still too much metaprogramming, but these are things
that are relatively easy to remove.

[SVN r79356]
2012-07-08 11:55:10 +00:00
Daniel James f5292fd9f7 Unordered: Simplify the object count stuff.
[SVN r79355]
2012-07-08 11:54:47 +00:00
Daniel James ada08d9459 Unordered: Turn off warnings-as-errors.
Getting spurious failures for gcc 4.0 and 4.8. It's more hassle than it's
worth.

[SVN r79354]
2012-07-08 11:54:21 +00:00
Daniel James 9a284b4106 Unordered: Remove some junk from the end of memory.hpp
[SVN r79353]
2012-07-08 11:54:01 +00:00
Daniel James 98083078a3 Unordered: Remove malloc_allocator.
It was originally introduced because of some issues with Boost.Test and older
compilers, neither of which I'm using now. Simplifies a few things.

[SVN r79352]
2012-07-08 11:53:39 +00:00
Daniel James b8d96be8f7 Unordered: Macro to simplifiy variadic/emplace_args creation.
[SVN r79351]
2012-07-08 11:53:16 +00:00
Daniel James 68edec9f97 Unordered: Remove old, unused function.
[SVN r79350]
2012-07-08 11:52:38 +00:00
Daniel James 39bafd7b10 Unordered: Reapply changes reverted in r78788.
[SVN r79163]
2012-06-28 20:58:56 +00:00
Daniel James c788780792 Unordered: Merge msvc 11 fix from trunk.
[SVN r78853]
2012-06-07 19:47:01 +00:00
Daniel James 0acb4ee3e6 Unordered: Document move insert.
Just a quick copy and paste for tonight's documentation build. May edit a bit
before release.

[SVN r78810]
2012-06-04 22:53:43 +00:00
Daniel James 893ebc5adb Unordered: Don't use std::allocator_traits on Visual C++ 11.
[SVN r78789]
2012-06-01 11:06:03 +00:00
Daniel James 7158700502 Unordered: Revert unmerged changes in trunk.
So that I can fix issues in the beta.


[SVN r78788]
2012-06-01 11:03:22 +00:00
Daniel James 1eac47a275 Unordered: Use Boost.Move in a few more places.
Should be better for compilers with variadic parameters, but no rvalue
references. If such a thing ever exists.

[SVN r78536]
2012-05-21 22:15:33 +00:00
Daniel James c6f0175c79 Unordered: Combine emplace_args + allocator_helpers.
[SVN r78535]
2012-05-21 22:14:59 +00:00
Daniel James e1416d0a3e Unordered: Fix bcp namespace fix. Fixes #6905.
[SVN r78534]
2012-05-21 22:08:19 +00:00
Daniel James 6031b66f99 Unordered: Fix namespaces for renaming in bcp. Refs #6905.
[SVN r78491]
2012-05-17 06:20:55 +00:00
Daniel James 808f1f939f Unordered: Merge unordered from trunk.
- Activate `std::allocator_traits` for gcc 4.7 and Visual C++ 11.
- Implement variadic construct in `boost::unordered::detail::allocator_traits`
  when variadics, rvalue references and SFINAE expression are available.
- Use variadic construct from `allocator_traits`, or when not available move
  the logic for constructing `value_type` to a lower level, so the container
  code is a bit simpler.
- Avoid `-Wshadow` warnings. Fixes #6190.
- Implement `reserve`. Fixes #6857.


[SVN r78432]
2012-05-12 08:14:05 +00:00
Daniel James d863f17673 Unordered: Try to fix Sun compile error.
The Sun compile tests have started failing, I'm not sure what triggered this,
but it seems to be confused by the various uses of the identifier `node`, so
try renaming the class and see if that improves things.

[SVN r78413]
2012-05-10 21:37:44 +00:00
Daniel James 24c08646f4 Unordered: Fix macros for picking construct/destroy.
[SVN r78378]
2012-05-08 11:02:29 +00:00
Daniel James 6604abe600 Unordered: allocator_helpers cleanup.
[SVN r78370]
2012-05-07 18:10:27 +00:00
Daniel James 39aed02e32 Unordered: Check that reserve works for both range and single element insert.
[SVN r78369]
2012-05-07 18:10:04 +00:00
Daniel James 6b44f3b887 Unordered: Fix destroy to match construct in last commit.
[SVN r78368]
2012-05-07 18:09:25 +00:00
Daniel James cd88cb4a30 Unordered: 'full construct' requires SFINAE expressions.
[SVN r78367]
2012-05-07 12:22:24 +00:00
Daniel James 32dc45b7bd Unordered: Implement reserve. Refs #6857.
[SVN r78365]
2012-05-07 10:58:32 +00:00
Daniel James 275b03e76b Unordered: Avoid -Wshadow warnings. Refs #6190.
[SVN r78364]
2012-05-07 10:57:35 +00:00
Daniel James 995ef1efdb Unordered: Use std::allocator_trait's variadic construct.
[SVN r78349]
2012-05-06 12:29:24 +00:00
Daniel James 8cb85937c4 Unordered: Reactivate std::allocator_traits for gcc 4.7, and try for Visual C++ 11
[SVN r78348]
2012-05-06 12:28:57 +00:00
Daniel James e615ac67c2 Unordered: allocator_helpers.hpp was moved.
[SVN r78347]
2012-05-06 12:28:05 +00:00
Daniel James 880d778ab6 Unordered: Missing revision from last merge.
[SVN r78320]
2012-05-03 22:29:25 +00:00
Daniel James a8cd8cdd0b Unordered/Hash: Merge from trunk.
[SVN r78319]
2012-05-03 22:05:21 +00:00
Daniel James 401df0f2fb Unordered/Hash: Release notes.
[SVN r78318]
2012-05-03 21:35:51 +00:00
Daniel James 531f6804ad Unordered: Disable std::allocator_traits on gcc for now.
[SVN r78166]
2012-04-23 20:52:08 +00:00
Daniel James d5230a874b Unordered: Rejig some of the emplace_args macro code. Refs #6784
This is a bit cleaner and will hopefully fix the Sun problems.

[SVN r77972]
2012-04-14 17:32:28 +00:00
Daniel James 030fd55d02 Unordered: Pull forward declarations out of detail/fwd.hpp
[SVN r77835]
2012-04-08 15:30:35 +00:00
Daniel James 626bb48013 Unordered: Use iterators in more of the implementation methods.
[SVN r77834]
2012-04-08 15:30:14 +00:00
Daniel James e64f82ed03 Unordered: Fix equality for multimap/multiset.
[SVN r77833]
2012-04-08 15:29:49 +00:00
Daniel James c8c71d0ad1 Unordered/hash: Avoid a gcc warning. Refs #6771
[SVN r77832]
2012-04-08 15:29:15 +00:00
Daniel James 4e759b4444 Unordered: Call policy functions as static functions.
[SVN r77831]
2012-04-08 15:28:26 +00:00
Marshall Clow 9f199eaa23 Updated Boost.Unordered to use BOOST_NO_0X_HDR_INITIALIZER_LIST instead of (soon to be deprecated) BOOST_NO_INITIALIZER_LISTS
[SVN r77154]
2012-03-02 16:43:58 +00:00
Daniel James 2fed2fbd9e Unordered: Hashing policy for 64 bit computers.
[SVN r77066]
2012-02-18 15:47:59 +00:00
Daniel James 29d63e378b Unordered: Remove unnecessary typename.
Oddly, newer versions of gcc don't complain about it.

[SVN r77043]
2012-02-16 20:53:45 +00:00
Daniel James 8a1a475c58 Unordered: Use container's allocator_traits for old Visual C++.
[SVN r77017]
2012-02-14 23:55:09 +00:00
Daniel James 08230efb44 Unordered: Use C++11 allocator_traits with gcc 4.7.
[SVN r76970]
2012-02-11 12:33:25 +00:00
Daniel James 2aee3add16 Unordered: Remove some of the smaller primes.
There's quite a high chance of collisions for these values.

[SVN r76969]
2012-02-11 12:33:02 +00:00
Daniel James f6b8d3957d Unordered: Remove unnecessary typename.
[SVN r76906]
2012-02-05 23:21:45 +00:00
Daniel James 992cc0b077 Unordered: Some C++11 allocator_traits fixes.
Can now be used with g++ 4.7. Not activating by default yet.

[SVN r76893]
2012-02-05 08:45:52 +00:00
Daniel James 2f92b12205 Unordered: Missing include in test header.
[SVN r76892]
2012-02-05 08:45:31 +00:00
Daniel James 2e80a82554 Unordered: Fix undefined macro warnings. Refs #6522.
Just removing the rv reference stuff in extract_keys. I don't it's
needed anyway.

[SVN r76891]
2012-02-05 08:44:22 +00:00
Daniel James 51d2e2564e Unordered: Add tests for when Boost.Move is activated.
[SVN r76415]
2012-01-11 22:23:49 +00:00
Daniel James 2665090568 Unordered: Use Boost.Move for variadic forwarding.
[SVN r76331]
2012-01-06 08:36:43 +00:00
Daniel James d70fcb8c25 Unordered: Make using Boost.Move optional.
[SVN r76330]
2012-01-06 08:35:51 +00:00
Daniel James ac0a2fe6c9 Fix 'occurred' in iostreams and unordered. Refs #6003
[SVN r76144]
2011-12-24 19:00:08 +00:00
Daniel James 6c09b89d0c Unordered: Change log for fairly minor changes.
[SVN r75907]
2011-12-11 21:36:26 +00:00
Daniel James 8f982c8b27 Unordered: Fix forwarding from emplace.
[SVN r75856]
2011-12-07 19:18:11 +00:00
Daniel James a61e876300 Unordered: emplace cleanup.
- Always construct iterator in detail for consistency.
- Move 0-argument emplace to start of overloads.

[SVN r75744]
2011-11-30 08:21:58 +00:00
Daniel James 684e40464f Unordered: Manually write out some overloads for emplace.
Clang creates horrific error messages for Boost.Preprocessor based code,
so for small number of arguments manually write out a few important
functions. Not doing this everywhere.

[SVN r75743]
2011-11-30 08:21:38 +00:00
Daniel James 2507fd78e3 Unordered: Move rebind into 'types' classes.
Makes the types in error messages a tad bit nicer.

[SVN r75742]
2011-11-30 08:21:04 +00:00
Daniel James 21f1fe8185 Unordered: Try to avoid warning from boost/cstdint.hpp.
[SVN r75607]
2011-11-22 22:13:12 +00:00
Daniel James aeea8e05ad Unordered: Fix gcc warning and re-enable warnings-as-errors for gcc.
[SVN r75599]
2011-11-21 23:21:11 +00:00
Daniel James 11c9955902 Unordered: Remove support for TR1 tuples. Refs #6111.
[SVN r75432]
2011-11-10 15:16:06 +00:00
Daniel James 9cb361f35e Unordered: construct_from_tuple for old versions of sun.
Not properly tested, as I haven't got the compiler fully working on my
machine.

[SVN r75341]
2011-11-06 09:34:54 +00:00
Daniel James c3477b2624 Unordered: Don't use SFINAE expression hack on Visual C++.
Sometimes it doesn't work. This means I can clean up the implementation
for other compilers, but I'll leave that for now.


[SVN r75167]
2011-10-29 16:31:40 +00:00
Daniel James a5dcc9dab0 Unordered: Return iterators in pairs instead of node_pointers.
It looks like the current version doesn't work with a correct
implementation of C++11 pairs since they don't use explicit conversions.
So just return the correct type in the first place.

Should probably be using iterators in other places as well. I was using
node_pointers everywhere due to some legacy from older versions.

[SVN r75158]
2011-10-28 17:42:51 +00:00
Daniel James 6ebc2e72ff Unordered: Rename B0, B1 etc. to avoid macro clash. Refs #6062.
[SVN r75123]
2011-10-26 21:31:27 +00:00
Daniel James d2a6ad8c72 Unordered: Documentation update.
[SVN r74962]
2011-10-16 10:31:25 +00:00
Daniel James 087962c16e Unordered: Fix move tests where moving returned values is not supported.
The propagate on move tests were failing because the values were being
copied not moved - so the container was check propagate on copy instead.
Because those tests are now weaker, and some new ones that will
hopefully work.

[SVN r74914]
2011-10-11 08:37:06 +00:00
Daniel James 4471e056f4 Unordered: Avoid passing UDTs through ....
[SVN r74913]
2011-10-11 08:36:23 +00:00
Daniel James b56a5ead66 Unordered: Some inspect fixes.
[SVN r74908]
2011-10-11 00:31:19 +00:00
Daniel James e3befdba7f Unordered: Update comparison between unordered and ordered containers.
[SVN r74907]
2011-10-11 00:30:59 +00:00
Daniel James 0cf8de5222 Unordered: Fix documentation markup error.
[SVN r74846]
2011-10-09 11:54:10 +00:00
Daniel James b6a6f530c0 Unordered: Only pair reference test where it's known to be okay.
[SVN r74845]
2011-10-09 11:53:38 +00:00
Daniel James 03245c80ff Unordered: Turn off warnings as errors and debug libs.
I'm getting a warning from another library. I don't really need to check
debug libs anymore - that was for container_fwd which is now tested in
details.

[SVN r74840]
2011-10-09 07:56:28 +00:00
Daniel James 2775ae2f2e Unordered: Correct fix for old gcc.
[SVN r74836]
2011-10-09 01:23:25 +00:00
Daniel James 8557a30592 Unordered: Fix dependent type.
[SVN r74832]
2011-10-09 00:47:08 +00:00
Daniel James fd530b87f6 Unordered: Remove use of BOOST_PP_ENUM_SHIFTED.
Doesn't seem to work on Intel's preprocessor.

[SVN r74813]
2011-10-08 17:39:54 +00:00
Daniel James 674d635024 Unordered: Move has_member into nested struct for sun.
[SVN r74812]
2011-10-08 17:39:36 +00:00
Daniel James f304e56818 Unordered: Stop using void_pointer.
Was breaking for allocators that don't have good enough support for
void_pointer. Which I suspect is pretty common.

[SVN r74800]
2011-10-08 12:17:27 +00:00
Daniel James 5a2bf64a65 Unordered: Just do member detection on older compilers.
[SVN r74799]
2011-10-08 12:17:09 +00:00
Daniel James f1b78931d1 Unordered: More misc. cleanup.
Including removing node.hpp.

[SVN r74775]
2011-10-07 08:19:53 +00:00
Daniel James 3d7b6c64b5 Unordered: some more formatting + namespaces
[SVN r74767]
2011-10-06 21:31:25 +00:00
Daniel James 597d93537d Unordered: More cleaning up.
Fix deprecated construct_impl and explicit namespaces in a few places.

[SVN r74766]
2011-10-06 21:06:35 +00:00
Daniel James 3a909c8747 Unordered: Better emplace_args implementation.
And some misc. cleanup.

[SVN r74750]
2011-10-06 08:03:25 +00:00
Daniel James ad38ecf6d8 Unordered: Remove some std::cout debugging. Oops.
[SVN r74746]
2011-10-05 22:05:52 +00:00
Daniel James dac1dc5837 Unordered: Reorganization to use void pointers and other things.
Helps allocators which can't use incomplete pointers, and avoid using
base pointers where that might not be possible.  And some other
reorganization. Storing arguments to emplace in a structure when
variadic template parameters aren't available. Changed some of the odd
design for working with older compilers.

[SVN r74742]
2011-10-05 19:45:14 +00:00
Daniel James c0aaf908c0 Unordered: Tweak member detection for sun.
Detect using a member pointer, rather than a member function pointer.
Sun seems to be happier with that.

[SVN r74605]
2011-09-28 23:50:27 +00:00
Daniel James b1d782285c Unordered: Remove void cast.
I don't think it's needed.

[SVN r74542]
2011-09-23 20:27:39 +00:00
Daniel James b0620a46ff Unordered: Don't use BOOST_UNORDERED_HAS_FUNCTION with Sun.
Something is causing the sun compiler to crash. I don't know if it's the
member detection or testing if the member if callable, so try disabling
the callable test to see if that works better.

[SVN r74541]
2011-09-23 20:27:22 +00:00
Daniel James 340c98d89a Unordered: New member function detection.
Based on Ion's `has_member_function_callable_with`.

[SVN r74532]
2011-09-22 23:56:49 +00:00
Daniel James 78241de393 Unordered: at is in the standard.
[SVN r74531]
2011-09-22 23:56:28 +00:00
Daniel James dbf7c9d6aa Unordered: Note about backwards compatability in emplace.
[SVN r74383]
2011-09-15 08:22:29 +00:00
Daniel James 983ad956e0 Unordered: Change log note about new emplace.
[SVN r74379]
2011-09-14 21:06:38 +00:00
Daniel James 45273ea6a5 Unordered: Remove more parts of rationale made unnecessary by C++11.
[SVN r74378]
2011-09-14 21:05:53 +00:00
Daniel James 9b82dcde10 Unordered: Update equality documentation.
[SVN r74377]
2011-09-14 21:05:13 +00:00
Daniel James b496bc3fa2 Unordered: fix swap documentation.
[SVN r74376]
2011-09-14 21:04:23 +00:00
Daniel James f8abb9633a Unordered: Revert [74315].
I checked it in due to some clumsy rebasing.


[SVN r74326]
2011-09-09 10:42:56 +00:00
Daniel James 76c37f7805 Unordered: Sunpro doesn't have nullary emplace().
[SVN r74319]
2011-09-08 21:11:16 +00:00
Daniel James 7d441864ec Unordered: Remove use of allocator utilities.
[SVN r74317]
2011-09-08 21:10:39 +00:00
Daniel James ccd895a356 Unordered: Extra check for vacpp's odd failure.
VACPP 11.0 appears to be detecting a move for nothing more than a
default initialised value.

[SVN r74316]
2011-09-08 21:10:18 +00:00
Daniel James 8ecdee5a93 Unordered: Try to fix vacpp's issue with select_on_container_copy_construction
[SVN r74315]
2011-09-08 21:09:56 +00:00
Daniel James 70c39ad5ea Unordered: Revert [74236].
On vacpp `has_select_on_container_copy_construction` was incorrectly returning
positive for a non-const `select_on_container_copy_construction`. This resulted
in a compile error as it tried to call it for a const allocator. The workaround
seemed to have just made things worse so I'm reverting it. It's actually not
that bad a problem as a non-const `select_on_container_copy_construction` is
probably a mistake.


[SVN r74294]
2011-09-07 10:01:25 +00:00
Daniel James 96fc0fa3c2 Unordered: Try to fix vacpp's issue with select_on_container_copy_construction
[SVN r74236]
2011-09-05 08:06:17 +00:00
Daniel James c101aec06c Unordered: Use destroy workaround for allocator_traits.
[SVN r74235]
2011-09-04 19:49:11 +00:00
Daniel James bd79d02049 Unordered: Remove unreachable code.
[SVN r74218]
2011-09-04 11:58:56 +00:00
Daniel James 0ea847a64e Unordered: Documentation changes.
[SVN r74194]
2011-09-02 08:29:23 +00:00
Daniel James 965e25c989 Unordered: Try to fix issues with moving non-class types.
[SVN r74193]
2011-09-02 08:28:52 +00:00
Daniel James a3ffd4a7c9 Unordered: Remove BOOST_DEDUCED_TYPENAME
[SVN r74192]
2011-09-02 08:28:19 +00:00
Daniel James 41b9b8d841 Unordered: Remove pair cast.
[SVN r74191]
2011-09-02 08:27:27 +00:00
Daniel James 26a47d33c1 Unordered: Use return type SFINAE, seems to be more portable.
[SVN r74182]
2011-09-01 08:26:36 +00:00
Daniel James 1154b5729a Unordered: Deprecate variadic pair construction emulation.
[SVN r74181]
2011-08-31 22:57:57 +00:00
Daniel James fd1aec2998 Unordered: Add option to use old equality implementation for backwards compatability.
[SVN r74180]
2011-08-31 22:23:01 +00:00
Daniel James 659b6fe8ba Unordered: Another attempt at member detection.
Another stab in the dark. Doing SFINAE in the return type appears to
work well, apart for Visual C++ 8.0. Will have to see how the test
results go for some compilers.

[SVN r74173]
2011-08-30 22:02:27 +00:00
Daniel James ceef4d6521 Unordered: Explicitly pick construct_impl overloads.
Still getting ambiguous call errors for some older compilers, so use SFINAE to
only enable a single overload for each arity.

[SVN r74171]
2011-08-30 22:01:54 +00:00
Daniel James 86b077b9a1 Unordered: Use quickbook 1.5
[SVN r74143]
2011-08-29 17:14:28 +00:00
Daniel James 28cdebe7a4 Unordered: Update erase reference.
[SVN r74142]
2011-08-29 17:14:09 +00:00
Daniel James d4087f64d9 Unordered: Fix boostbook errors.
[SVN r74141]
2011-08-29 17:13:27 +00:00
Daniel James 4ec5a0eebd Unordered: updating reference documentation.
[SVN r74137]
2011-08-29 15:23:32 +00:00
Daniel James f58a3fc3eb Unordered: Another breaking change.
[SVN r74136]
2011-08-29 15:22:00 +00:00
Daniel James 11562b3285 Unordered: Update docs since it's now based on C++11
[SVN r74135]
2011-08-29 15:21:04 +00:00
Daniel James 568fd1758d Unordered: More info on C++11 compliance.
[SVN r74134]
2011-08-29 15:20:27 +00:00
Daniel James f64b5ba3f8 Unordered: Account for cost of creating tuple.
[SVN r74133]
2011-08-29 15:19:40 +00:00
Daniel James 395c744d6f Unordered: More portability changes.
[SVN r74122]
2011-08-29 11:10:09 +00:00
Daniel James 155077cba0 Unordered: Support piecewise pair construction.
Will need to deprecate the old variadic style pair construction, also
should look into extract_key, was written for compatibility with older
compilers that are no longer supported.

[SVN r74119]
2011-08-29 09:40:41 +00:00
Daniel James 4dcf34c264 Unordered: Restore at_tests.
[SVN r74108]
2011-08-28 15:43:08 +00:00
Daniel James 4bf3b1bfc5 Unordered: Support optional allocator methods.
Only for compilers with SFINAE expressions and recent versions of Visual
C++. Also fix Visual C++ 8, and use BOOST_UNORDERED_ prefix for all
macros.

[SVN r74106]
2011-08-28 15:36:58 +00:00
Daniel James 6bc99ac0c2 Unordered: Hopefully vacpp will like this more.
[SVN r74103]
2011-08-28 11:31:43 +00:00
Daniel James 09e856562a Unordered: Try to avoid warning on sun.
[SVN r74102]
2011-08-28 11:31:23 +00:00
Daniel James 5dd13dbfb3 Unordered: Try to avoid std::size_t to double warnings.
Maybe I should use long double?

[SVN r74087]
2011-08-27 11:53:48 +00:00
Daniel James 9ae19a64d7 Unordered: Fix more calls to std::forward.
[SVN r74086]
2011-08-27 11:29:04 +00:00
Daniel James bd13f2b1ad Unordered: Fix some calls to std::forward.
[SVN r74074]
2011-08-26 15:28:56 +00:00
Daniel James d09bbba6c1 Unordered: Missing limits header in tests.
[SVN r74073]
2011-08-26 15:24:47 +00:00
Daniel James 3f4d031c43 Unordered: Remove extra ';'.
[SVN r74072]
2011-08-26 15:24:16 +00:00
Daniel James 674b39243f Unordered: More robust construct_impl.
[SVN r74068]
2011-08-26 08:12:08 +00:00
Daniel James 099a893678 Unordered: More portable allocator_traits.
[SVN r74067]
2011-08-26 08:11:46 +00:00
Daniel James cfd52c8f38 Unordered: Fix compiler check in unnecessary_copy_tests.
[SVN r74066]
2011-08-26 08:11:12 +00:00
Daniel James e295541dae Unordered: Try to make VC++ 8 happy.
[SVN r73973]
2011-08-20 23:34:59 +00:00
Daniel James 785a6def3b Unordered: Remove another use of BOOST_RV_REF for sun.
[SVN r73972]
2011-08-20 23:34:38 +00:00
Daniel James 53bdec8aab Unordered: More unnecessary_copy_tests tweaks.
[SVN r73971]
2011-08-20 23:34:14 +00:00
Daniel James 5191897696 Unordered: Compliance TODO note
[SVN r73895]
2011-08-18 19:29:22 +00:00
Daniel James 2ecfa0e08c Unordered: Fix unnecessary_copy_tests failures.
[SVN r73894]
2011-08-18 19:29:02 +00:00
Daniel James c001139465 Unordered: detab
[SVN r73893]
2011-08-18 19:28:41 +00:00
Daniel James e3353a445a Unordered: Fix some test failures.
[SVN r73856]
2011-08-17 21:29:41 +00:00
Daniel James ce779452ba Unordered: Fix gcc error + warning.
[SVN r73839]
2011-08-17 07:43:43 +00:00
Daniel James eb8b8295a1 Unordered: Fix an xml error in the docs.
[SVN r73830]
2011-08-16 22:19:00 +00:00
Daniel James 94c9c61142 Unordered: Document new changes and C++11 compliance.
[SVN r73829]
2011-08-16 22:18:09 +00:00
Daniel James 11e390bf42 Unordered: Use Boost.Move in minimal tests.
[SVN r73828]
2011-08-16 22:17:11 +00:00
Daniel James a8fdf19c91 Unordered: Test types that are only destructible.
[SVN r73820]
2011-08-16 18:08:23 +00:00
Daniel James 08bca9a35f Unordered: Support moving allocators.
[SVN r73805]
2011-08-15 21:34:01 +00:00
Daniel James 1db630d5c9 Unordered: Enable the better select_on_container_copy_construction detection for recent Visual C++.
[SVN r73799]
2011-08-15 20:24:12 +00:00
Daniel James bbad921022 Unordered: Fix some portability issues in tests.
- Simplify mechanism for detecting traits of test allocators. There were
  some portability issues, but rather than fix them I've just gone for a
  simpler mechanism. Does mean that the relevant tests can't be run for
  other allocators.
- Fix a couple of unnecessary_copy_tests, whose results were the wrong
  way round.
- It appears that Visual C++ only implements RVO for implicitly defined
  copy constructors in debug mode, so adjust a move_test to account for
  the extra copies now that the copy constructors are explicitly
  defined.

[SVN r73798]
2011-08-15 20:23:29 +00:00
Daniel James f64cf03e1d Unordered: Implement select_on_container_copy_construction support.
[SVN r73772]
2011-08-15 07:48:53 +00:00
Daniel James 559122f67a Unordered: Small improvements for windows.
[SVN r73760]
2011-08-14 21:03:18 +00:00
Daniel James 431f2abfee Unordered: Alternative member detection.
Hopefully the Sun compiler will like this.

[SVN r73757]
2011-08-14 18:53:50 +00:00
Daniel James 5f622027cd Unordered: Implement allocator propagation on assignment.
It's pretty messy because I'm trying to avoid swapping allocators in
these cases. I'm also not sure of the exception requirements of
allocator swap and assignment.

[SVN r73756]
2011-08-14 18:53:29 +00:00
Daniel James fa97494cc8 Unordered: Move some of the unordered implementation.
[SVN r73755]
2011-08-14 18:53:03 +00:00
Daniel James f4d4975077 Unordered: Count instances in some tests.
[SVN r73754]
2011-08-14 18:52:43 +00:00
Daniel James f030480e44 Unordered: detab.
[SVN r73753]
2011-08-14 18:52:20 +00:00
Daniel James 435c21c155 Unordered: Qualify calls to addressof.
Hopefully this will fix C++0x compilers. Although I don't have one at
hand to test.

[SVN r73690]
2011-08-12 06:26:25 +00:00
Daniel James 7438d7a02f Unordered: Move around assignment stuff.
[SVN r73681]
2011-08-11 21:19:05 +00:00
Daniel James 0e5930b8dc Unordred: Implement propagate_on_container_swap.
[SVN r73680]
2011-08-11 21:18:43 +00:00
Daniel James eacca89d4e Unordered: Starting to implement allocator propagation.
[SVN r73679]
2011-08-11 21:18:19 +00:00
Daniel James 99e6bef4ef Unordered: Starting to support allocator_traits.
[SVN r73678]
2011-08-11 21:17:57 +00:00
Daniel James 3d5314b5f5 Unordered: Don't use BOOST_RV_REF with Sun compilers.
[SVN r73593]
2011-08-07 10:22:41 +00:00
Daniel James f0517463a5 Unordered: Better std::forward/move configuration.
[SVN r73592]
2011-08-07 08:55:28 +00:00
Daniel James c9e0fb9730 Unordered: Update unnecessary_copy_tests for Boost.Move.
Seems to be better in some cases. For example, better forwarding if
rvalue references are supported but variadic template parameters aren't.
Also can use `boost::move` when inserting.

Older versions of gcc still fail this test. They perform more moves than
expected. It might be a limitation of Boost.Move, or maybe just poor
copy optimization.

[SVN r73539]
2011-08-04 22:54:26 +00:00
Daniel James d86a4b0c2f Unordered: Use Boost.Move for emplace and insert.
[SVN r73520]
2011-08-03 23:52:37 +00:00
Daniel James eced4266c2 Unordered: Copy and assign using Boost.Move.
[SVN r73503]
2011-08-03 08:34:33 +00:00
Daniel James fc483e60bc Unordered: Fix link to swap issue.
[SVN r73502]
2011-08-03 08:34:11 +00:00
Daniel James 910cd41c47 Unordered: Generate ref docs using php.
[SVN r73501]
2011-08-03 08:33:37 +00:00
Daniel James b4e1d32e85 Unordered: detab.
[SVN r72906]
2011-07-04 21:55:40 +00:00
Daniel James ff66f79721 Unordered: Import functions into boost namespace.
[SVN r72905]
2011-07-04 21:52:17 +00:00
Daniel James 8b610a6d34 Unordered: Work around for compilers which don't support template friend members.
[SVN r72523]
2011-06-09 19:48:34 +00:00
Daniel James 20e923ba0d Unordered: Move the implementation into a namespace.
Although it typically won't prevent ADL, because of boost::hash.

[SVN r72391]
2011-06-04 16:17:07 +00:00
Daniel James 4777eaf367 Unordered: remove some dead, bad code.
[SVN r72390]
2011-06-04 16:15:27 +00:00
Daniel James a40422fada Unordered: remove use of the 'or' keyword.
[SVN r71602]
2011-04-29 11:03:29 +00:00
Daniel James b1912055a9 Unordered: Fix some errors in the equality tests.
[SVN r71363]
2011-04-17 21:27:38 +00:00
Daniel James e8714d79b2 Unordered: Implement C++0x equality.
[SVN r71354]
2011-04-17 16:23:25 +00:00
Daniel James f8e2a917f9 Unordered: 2 phase lookup fix for clang.
[SVN r71352]
2011-04-17 14:27:08 +00:00
Daniel James 140e8852e8 Unordered: fix some gcc issues.
[SVN r71346]
2011-04-17 00:31:35 +00:00
Daniel James 547e141166 Unordered: Overhaul the implementation.
Store nodes in a single linked list, with hash values so that their
buckets can be found when needed. Iterators now only have to store a
pointer to the node and don't have to iterate over empty buckets to
reach the next node. This allows the container to meet the iterator
requirements - fixing the speed issues with `equal_range` and `erase`.

Also, define iterators in their own namespace, so that they don't
accidentally pull in detail functions via ADL.

I've simplified the code slightly by removing some of the special
cases for empty containers. Renamed a few things as well and other
minor changes that were made as I went along.

[SVN r71327]
2011-04-16 18:47:33 +00:00
Daniel James d9c49a6cde Don't require explicit conversion in pairs in unordered's insert tests.
In the draft standard the std::pair constructor from another pair is
only considered when overloading if both members are implicitly
constructible to their corresponding members. This breaks one of the
unordered tests which required an explicit conversion, so change it to
only require an implicit conversion.

[SVN r70028]
2011-03-16 21:34:08 +00:00
Daniel James 8ade57b9e3 Remove workaround for ancient gcc verisons.
[SVN r70027]
2011-03-16 21:33:41 +00:00
Daniel James a4750fbdba Make unnecessary_copy_tests a bit more lenient.
I'm not sure if those extra moves are avoidable, but I'll allow them for
now. They shouldn't hurt much.

[SVN r68446]
2011-01-25 20:15:27 +00:00
Daniel James a33949a0a5 Add copy constructors and assignment operators when using rvalue references. Refs #5119.
[SVN r68445]
2011-01-25 20:13:43 +00:00
Daniel James 4d57147c3d Fix tabs and files without copyright.
[SVN r67612]
2011-01-03 12:43:34 +00:00
Daniel James 3d7abd9cbe Avoid -Wconversion warnings in unordered & hash.
[SVN r67170]
2010-12-11 14:43:00 +00:00
Daniel James 5a81ca6ffe Import boostbook/quickbook in unordered and hash docs.
[SVN r67091]
2010-12-07 20:45:08 +00:00
Daniel James b9188caf7d Fix [66556] - Remove clang workaround.
I accidentaly removed the good code and left the workaround in. Also, a
correction to the comment: I think bug was only in a unreleased version
of clang.

[SVN r66567]
2010-11-14 11:43:49 +00:00
Daniel James df726c038f Remove some 'always_show_run_output' flags.
[SVN r66566]
2010-11-14 11:42:58 +00:00
Daniel James 14e0e1afc2 Less use of the ampersand operator in unordered.
[SVN r66557]
2010-11-13 12:31:54 +00:00
Daniel James 2c1a8894cb Remove clang workaround.
Clang from llvm 2.8 doesn't need it. Clang form llvm 2.7 isn't
supported.

[SVN r66556]
2010-11-13 12:30:45 +00:00
Daniel James a49c76c69c More comments describing the unordered internals.
And fix a couple of small mistakes in the existing comments.

[SVN r66555]
2010-11-13 12:30:06 +00:00
Daniel James eb04f68351 Call forward declared functions from templates in unordered tests.
Borland is having some issues with the existing tests, since they call
inline functions before they're defined. It might be right to, although
all the other compilers are fine with it. But the test isn't really what
the forward headers are intended for. Try to make the tests better
represent the intent, and possibly work on Borland.

[SVN r66428]
2010-11-07 14:43:50 +00:00
Daniel James 77bd36d038 Declare inline functions as inline.
[SVN r66193]
2010-10-25 21:59:52 +00:00
Daniel James 1b85f812af Missing copy_iterator methods.
[SVN r66137]
2010-10-21 20:34:39 +00:00
Daniel James daad24388c Fix iterator insert bug in unordered_set/unordered_map.
[SVN r66136]
2010-10-21 20:23:37 +00:00
Daniel James 0cbd02d3cc Fix images in standalone unordered documentation.
[SVN r63451]
2010-06-30 12:05:36 +00:00
Daniel James 3a13ddb4a3 Don't use _GLIBCXX_DEBUG on darwin.
It isn't supported by Apple's gcc 4.2.

[SVN r63449]
2010-06-30 12:04:41 +00:00
Daniel James 7b272c85d5 Missing bracket.
[SVN r63392]
2010-06-27 16:58:48 +00:00
Daniel James 5edc45349f Revert changes for sun 5.9.
Nobody seems to be running the tests now.


[SVN r62117]
2010-05-21 07:06:33 +00:00
Daniel James dfaa61b666 Another inline.
[SVN r61872]
2010-05-09 07:24:47 +00:00
Daniel James 076e195cac Define several methods inline.
Sun 5.9 was having some issues.

[SVN r61831]
2010-05-06 20:13:25 +00:00
Daniel James 71a8e56ae3 Move equivalent and unique hash tables into their own headers.
[SVN r61830]
2010-05-06 20:12:40 +00:00
Daniel James ef79fea0b7 The clang workaround broke some compilers, so only use it for clang.
[SVN r61529]
2010-04-24 12:59:35 +00:00
Daniel James ea33b5d134 Fix clang warnings in unordered tests.
[SVN r61505]
2010-04-23 07:26:43 +00:00
Daniel James 5bab4d4360 Work around friend bug in clang.
[SVN r61504]
2010-04-23 07:25:53 +00:00
Daniel James 10e24f93c4 Unordered/hash release notes.
[SVN r61356]
2010-04-18 13:20:45 +00:00
Daniel James 00cebc3dfb Use boost::throw_exception in unordered.
[SVN r60983]
2010-03-31 21:42:08 +00:00
Daniel James ee034e23bb Add quick_erase to the unordered containers. Refs #3966.
[SVN r60754]
2010-03-22 00:42:07 +00:00
Daniel James 1d02663275 Try to avoid a warning.
[SVN r59956]
2010-02-26 20:50:21 +00:00
Daniel James e594f1eda7 Remove deprecated macros for hash and unordered's tests.
[SVN r59708]
2010-02-16 22:33:10 +00:00
Daniel James 1bcb5f8b6f Take advantage of the simplified parameters.
[SVN r59707]
2010-02-16 22:32:49 +00:00
Daniel James 06f63fdc0d Stop using the deprecated BOOST_HAS_ macros in unordered and hash.
[SVN r59697]
2010-02-15 23:01:06 +00:00
Daniel James 7efcf9ccff Set length of primes inside template on Sun C++. Refs #3854
[SVN r59200]
2010-01-21 18:01:53 +00:00
Daniel James 6649b4df3c Update changelogs and slightly improved reference documentation for new release.
[SVN r58805]
2010-01-08 06:43:57 +00:00
Daniel James 71096f4d26 Formatting changes, mostly to fit within 80 characters.
Also, some C casts converted to static_cast.

[SVN r58692]
2010-01-04 22:49:39 +00:00
Daniel James 0f0161a5a2 Add codegear compatibility to the changes.
[SVN r58406]
2009-12-15 22:53:54 +00:00
Daniel James b99382b551 Add templated find overload for compatible keys.
[SVN r58405]
2009-12-15 22:53:33 +00:00
Daniel James 493f905598 Fix the return type of find in the unordered reference documentation.
[SVN r58404]
2009-12-15 22:53:08 +00:00
Daniel James 4e6292b439 Implement an alternative erase function that doesn't return an iterator.
Ref #3693

[SVN r58403]
2009-12-15 22:52:52 +00:00
Daniel James 2f0a94bcfd Add missing std:: qualifier to ptrdiff_t. Refs #3773.
[SVN r58402]
2009-12-15 22:42:04 +00:00
Daniel James 618a51df13 Turn off warnings as errors on gcc/darwin because the integer library currently causes some warnings.
[SVN r58394]
2009-12-15 13:16:32 +00:00
Daniel James 18a5010436 Remove use of iterator_adaptor in unordered tests.
[SVN r58144]
2009-12-04 19:44:34 +00:00
Daniel James c8b893cb77 Workaround codegear ICE.
It seems that the problem is calling sizeof on a dependent type when the
containers have only been used by reference. So by putting in these
dummy structures with the containers as members, it helps the compiler
instantiate the class to the level where sizeof works. I hope.

[SVN r58130]
2009-12-04 00:51:50 +00:00
Daniel James a1252fcc0e Use consistent names for template parameters.
I'm trying to fix the codegear ICEs, but it's hard to tell the cause.
Since the error happens operator== I suspect it's either to do
with defining friend functions with different template names or
something to do with friend functions in general. This is the first stab
in the dark at fixing this.

[SVN r58062]
2009-11-30 18:25:26 +00:00
Daniel James ef67d9ae12 Document the unordered changes.
[SVN r58004]
2009-11-28 11:46:24 +00:00
Daniel James 3e638049ec Try to support incomplete types for Sun - at the expense of zero argument emplace.
[SVN r58002]
2009-11-28 11:46:05 +00:00
Daniel James 7f59e8e058 Better testing of incomplete types.
[SVN r57975]
2009-11-27 19:43:06 +00:00
Daniel James 7023460394 Suppress a warning that's in the windows mobile system headers.
[SVN r57963]
2009-11-26 23:15:30 +00:00
Daniel James 0dcf1b5cd2 Fix the version check when suppressing warnings.
[SVN r57962]
2009-11-26 23:14:53 +00:00
Daniel James 7b2c5189b3 Suppress some warnings on visual c++ 7.1.
[SVN r57921]
2009-11-25 09:14:16 +00:00
Daniel James d3fe62a646 Try to avoid an odd warning from Visual C++
[SVN r57919]
2009-11-25 09:09:25 +00:00
Daniel James 1f17294cd3 Use remove_const again.
[SVN r57840]
2009-11-21 20:37:50 +00:00
Daniel James 3882a61065 Inspect fixes.
[SVN r57838]
2009-11-21 19:40:28 +00:00
Daniel James df72c4886f Support incomplete template parameters to unordered containers.
[SVN r57798]
2009-11-20 08:03:26 +00:00
Daniel James 26c72f9860 Use 'E' for key extractor, freeing 'K' for key.
[SVN r57797]
2009-11-20 08:02:48 +00:00
Daniel James 55957bbab5 Some more warning fixes for Visual C++ 7.1
[SVN r57719]
2009-11-16 23:56:37 +00:00
Daniel James ab843eb587 Fix a warning on Visual C++ 7.1. Although, I don't think I'm going to be warning free on the compiler.
[SVN r57617]
2009-11-12 21:36:27 +00:00
Daniel James 4438b8e017 Fix a warning that only shows up in release builds.
[SVN r57556]
2009-11-10 20:07:50 +00:00
Daniel James 5747836754 Change unordered move tests to be more lenient on compilers without NRVO. Will probably need to reintroduce some of the failure markup later.
[SVN r57550]
2009-11-10 18:17:53 +00:00
Daniel James ba5c383877 Stricter warnings for unordered and hash.
There are still warnings in hash_complex_test.

[SVN r57537]
2009-11-10 08:15:55 +00:00
Daniel James b4f08db391 Remove 'grouped' from hash_table as it isn't used and is a bit confusing.
[SVN r57153]
2009-10-25 10:55:27 +00:00
Daniel James 060acb3f25 Slightly rearrange the unordered container headers so that prev_prime is defined before it's used.
[SVN r57152]
2009-10-25 10:55:08 +00:00
Daniel James 8727de1a1b Remove insert empty initializer lists, as there's a bug in gcc.
[SVN r57151]
2009-10-25 10:54:53 +00:00
Daniel James 8cde8d1252 Fix the intel strict flag.
[SVN r57150]
2009-10-25 10:54:28 +00:00
Daniel James 6bac25221a Fix unordered for intel strict.
[SVN r57139]
2009-10-24 17:53:03 +00:00
Daniel James 5bedbde746 Update the intel compile flags.
[SVN r57126]
2009-10-24 11:56:30 +00:00
Daniel James 2fdd33381c Fix allocator for construct from initializer list.
[SVN r57006]
2009-10-19 19:32:09 +00:00
Daniel James 8d4b503e56 Use normal emplace implementation for emplace_hint and insert with hint.
There's a bug in the emplace_hint implementation for unordered
containers with equivalent keys. Since my tests missed it, I'm just
going to use the normal emplace implementation until I write better
tests.

[SVN r57005]
2009-10-19 19:24:33 +00:00
Daniel James 6c24cccf96 Add release notes for unordered.
[SVN r56988]
2009-10-18 20:18:28 +00:00
Troy D. Straszheim 51fdfa7ac7 rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
Daniel James 3dff89c240 Correct macro checks for initializer lists.
[SVN r56844]
2009-10-14 20:30:48 +00:00
Daniel James 4e07c94502 Copy the unordered and hash CMake files from release.
[SVN r56704]
2009-10-10 15:09:02 +00:00
Daniel James 854dc0b353 Various inspect fixes.
[SVN r56603]
2009-10-05 21:29:39 +00:00
Daniel James 373791d0b2 Detab.
[SVN r56571]
2009-10-04 10:37:56 +00:00
Daniel James fe3d612fe0 Clean up some unordered TODOs.
[SVN r56570]
2009-10-04 10:37:36 +00:00
Daniel James ae0c97a77a Make sure inserting from a range of types other than the value type is better tested.
[SVN r56562]
2009-10-03 16:42:20 +00:00
Daniel James 788a3661a2 Update the unordered rationale.
[SVN r56561]
2009-10-03 16:42:00 +00:00
Daniel James 1e24f85fbc Insert using initializer lists.
[SVN r56560]
2009-10-03 16:41:32 +00:00
Daniel James 4601f5c51f Stricter insert exception tests.
[SVN r56559]
2009-10-03 16:41:11 +00:00
Daniel James 55eafdf0ee Update reference docs to latest version of draft standard and fill in
some missing details.

[SVN r56558]
2009-10-03 16:40:53 +00:00
Daniel James 63e04cfb60 Fix the iterator category.
[SVN r56557]
2009-10-03 16:40:26 +00:00
Daniel James d0a3efab6a Just remove the test since the test itself doesn't work on most compilers.
[SVN r56468]
2009-09-29 07:46:44 +00:00
Daniel James 2b8680d2c4 Remove the optimization for std::pair with a key reference. It'll be too much hassle to get a very unusual use case to work on all compilers.
[SVN r56461]
2009-09-28 23:06:03 +00:00
Daniel James 31cd8f4e16 Try supporting reference parameters in pairs. Probably not required.
[SVN r56441]
2009-09-27 19:12:04 +00:00
Daniel James b75b7dd5ac Remove temporary test.
[SVN r56374]
2009-09-24 20:42:19 +00:00
Daniel James 437a35feaa Remove the emplace_hint implementation for unique containers as it isn't really used and seems to be causing sun 5.7 problems.
[SVN r56363]
2009-09-22 22:39:17 +00:00
Daniel James f76af2d0c8 Another std::max.
[SVN r56362]
2009-09-22 22:39:00 +00:00
Daniel James efbf13685e Use std::max.
[SVN r56349]
2009-09-21 21:18:21 +00:00
Daniel James 08d533cb88 Fix a bug that was causing unnecessary rehahes.
[SVN r56348]
2009-09-21 21:18:01 +00:00
Daniel James ff6e457651 Fix bug where container was reducing the number of buckets.
[SVN r56347]
2009-09-21 21:17:40 +00:00
Daniel James 965c2ae89c Slightly more consistent variable names. In detail 'n' is now always a node pointer.
[SVN r56346]
2009-09-21 21:17:19 +00:00
Daniel James 78b078f41d Since all the compilers support out of line template members use them
and lots of other things.

[SVN r56329]
2009-09-20 21:55:15 +00:00
Daniel James 491fa330f6 Move size_ and cached_begin_bucket_ into table, rename hash_table_manager hash_buckets.
[SVN r56010]
2009-09-04 07:03:04 +00:00
Daniel James 9ec148aec5 Fix link to n2691.
[SVN r56009]
2009-09-04 07:02:28 +00:00
Daniel James 7598d0d49b Add a small test to see if the tested compilers support out of line template methods.
[SVN r55992]
2009-09-03 07:37:30 +00:00
Daniel James 6a8506d959 Remove some old Visual C++ workarounds.
[SVN r55991]
2009-09-03 07:37:14 +00:00
Daniel James 7fe53ef5a3 Combine hash_structure and hash_table_manager.
[SVN r55990]
2009-09-03 07:36:21 +00:00
Daniel James 1743ed118d Remove 'static' from next_node and node_count. Will hopefully make vacpp happy.
[SVN r55922]
2009-08-31 15:33:49 +00:00
Daniel James 848b73f99f Remove a few unused parameters.
[SVN r55921]
2009-08-31 15:33:28 +00:00
Daniel James ccc88ecf0a Remove unnecessary BOOST_DEDUCED_TYPENAMEs
[SVN r55902]
2009-08-31 10:39:40 +00:00
Daniel James c40cb50fe5 Detab.
[SVN r55901]
2009-08-31 10:39:25 +00:00
Daniel James 386d9f28d7 Initial checkin of new version of Boost.Unordered.
- More template use, less preprocessor use.
 - Removed some of the Visual C++ 6 workarounds.
 - Reduced memory use of the main object.
 - Split into smaller headers.

[SVN r55878]
2009-08-30 16:42:28 +00:00
Daniel James 4350660626 Remove allocator_constructor since it's never used.
[SVN r55877]
2009-08-30 16:33:42 +00:00
Daniel James 1632522967 Update the reference documentation to mention that emplace is now emulated.
[SVN r55185]
2009-07-26 19:00:40 +00:00
Daniel James 178154082f Some extra changelog notes.
[SVN r55184]
2009-07-26 18:59:33 +00:00
Troy D. Straszheim d5dac9bdae Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
Daniel James cf363355df Try to work around an odd Visual C++ 8 bug.
[SVN r55138]
2009-07-23 22:17:20 +00:00
Daniel James ca018bfba6 Remove the emulation of single argument C++0x std::pair constructor.
[SVN r55132]
2009-07-23 17:53:59 +00:00
Daniel James 3c48fa3818 Adjust the unordered defaults so that emplace takes more parameters and less buckets are created by default.
[SVN r55100]
2009-07-22 22:38:08 +00:00
Daniel James 7bc588d8df Fix the insert tests when there is a small number of buckets.
[SVN r55099]
2009-07-22 22:37:52 +00:00
Daniel James 6d1aece43a Add constructors to the methods for controlling bucket size in unordered containers.
[SVN r54914]
2009-07-12 18:03:35 +00:00
Daniel James 7e1dbc4cb7 Fix the unordered_map declaration in the tutorial. Fixes #3119.
[SVN r53552]
2009-06-01 19:22:27 +00:00
Daniel James 2b09a34467 Get the type of the initializer_list right.
[SVN r53550]
2009-06-01 19:17:49 +00:00
Daniel James 78ea3024b5 Fix tests for when the library has support for initializer lists but the compiler doesn't.
[SVN r53525]
2009-06-01 06:50:37 +00:00
Daniel James cec1891586 Disable incorrect Visual C++ 64-bit warnings. Ref #3082.
[SVN r53505]
2009-05-31 15:50:56 +00:00
Daniel James 6d8ce11934 Remove a couple of old uses of BOOST_NO_INITIALIZER_LISTS.
[SVN r53367]
2009-05-28 22:06:42 +00:00
Daniel James b83a73ab40 Remove an unused function.
[SVN r53318]
2009-05-27 18:32:38 +00:00
Daniel James caa0b7cdf6 Fix a change accidentally included in the last commit.
[SVN r53317]
2009-05-27 18:32:22 +00:00
Daniel James 46caec7d77 Some workarounds for old versions of Borland.
[SVN r53316]
2009-05-27 18:19:32 +00:00
Daniel James 04234cecee Use lightweight_test for unordered.
[SVN r53314]
2009-05-27 17:44:09 +00:00
Daniel James 84ff0c3227 Remove obsolete comment.
[SVN r53312]
2009-05-27 17:43:22 +00:00
Daniel James 35a3894a88 Missing changelog entry.
[SVN r53311]
2009-05-27 17:42:01 +00:00
Daniel James bde5df043c Unordered change log for explicit destructors.
[SVN r53256]
2009-05-25 19:45:23 +00:00
Daniel James 8f70ddf4ef Unordered change log.
[SVN r53255]
2009-05-25 19:45:06 +00:00
Daniel James cfc134b871 Add explicit destructors to the unordered containers. Refs #2908.
Isn't really needed but it doesn't hurt.

[SVN r53253]
2009-05-25 19:14:07 +00:00
Daniel James 20c9360528 Better configuration for boost.unordered.
[SVN r53127]
2009-05-20 06:43:38 +00:00
Daniel James 09b239ed28 Merge emplace support for sandbox - but without move support.
[SVN r52885]
2009-05-10 21:25:09 +00:00
Daniel James 294d58d2fe Cherrypick some unordered container changes from sandbox. Not including
anything which depends on the new move library.

------------------------------------------------------------------------
r52746 | danieljames | 2009-05-03 11:12:30 +0100 (Sun, 03 May 2009) | 1 line

Merge latest unordered container changes.
------------------------------------------------------------------------
r52747 | danieljames | 2009-05-03 11:15:35 +0100 (Sun, 03 May 2009) | 4 lines

Put the C++0x emplace implementations before the non-C++0x versions.

I'm going to change the non-C++0x to be macro heavy emulations of the
C++0x versions, so this will put the readable version first.
------------------------------------------------------------------------
r52748 | danieljames | 2009-05-03 11:15:44 +0100 (Sun, 03 May 2009) | 1 line

Refactor the unordered implementation a tad, to make implementing emplace less painful.
------------------------------------------------------------------------

[SVN r52884]
2009-05-10 21:24:41 +00:00
Daniel James 3e70155100 Use a preprocessor sequence for the primes.
This feels like overkill but it seems to be the most reliable way to ensure
that the length is correct. I obviously can't be trusted to get it right, and
the template hack seems to prevent Boost.Range from working.

[SVN r52711]
2009-05-01 20:50:32 +00:00
Daniel James ce379f7bb5 Fix the prime number list length in unordered.
[SVN r52674]
2009-04-30 05:10:57 +00:00
Daniel James f8e1ec8d2b Revert changes to unordered, as the test fails on most compilers.
[SVN r52673]
2009-04-30 05:08:40 +00:00
Daniel James 24091f8bd8 Don't test prime_list::length on Visual C++.
Checking the array size doesn't seem to work on it.

[SVN r52669]
2009-04-29 21:43:41 +00:00
Daniel James 4c3c18467c Fix the length of the prime number list. Refs #2975
[SVN r52658]
2009-04-29 10:05:17 +00:00
Daniel James 3f0e2b478b Add stream output to the count test helper for unordered.
[SVN r52397]
2009-04-14 17:51:34 +00:00
Daniel James ac2409627a Use emplace instead of insert in the backend as it's more appropriate.
[SVN r52394]
2009-04-14 17:23:51 +00:00
Daniel James a07e4c5810 Implement full extract_key for compilers without SFINAE and variadic
templates.

[SVN r52393]
2009-04-14 17:23:37 +00:00
Daniel James 5a86d08271 Note change to operator[] in the unordered release notes.
[SVN r52350]
2009-04-12 10:50:57 +00:00
Daniel James 4ac0a12a83 Avoid an unnecessary copy in 'operator[]'
[SVN r52224]
2009-04-06 22:51:36 +00:00
Daniel James 290c7566ff Changelog for unordered and hash.
[SVN r52084]
2009-03-31 19:43:58 +00:00
Daniel James 6ccc68b15c Give up and use another macro to destruct values.
[SVN r51995]
2009-03-26 21:09:51 +00:00
Daniel James 188bcafdec Try to destruct values in a way that all compilers might like.
[SVN r51983]
2009-03-26 07:00:46 +00:00
Daniel James 3a8739cd60 Revert [51409]
It isn't working on Borland.

[SVN r51982]
2009-03-26 07:00:21 +00:00
Daniel James 2bc986ecbc Use paragraphs inside purpose tags.
[SVN r51802]
2009-03-16 20:21:05 +00:00
Daniel James 638accbec4 Update copyright dates in hash and unordered.
[SVN r51667]
2009-03-09 20:56:23 +00:00
Daniel James d8fb4f4c38 Detab.
[SVN r51644]
2009-03-08 09:44:51 +00:00
Daniel James 3e55934381 Make the sort stable.
Doesn't really matter, but it might as well be.

[SVN r51505]
2009-03-01 14:15:39 +00:00
Daniel James 40a89ac649 Add missing return for operator=.
[SVN r51504]
2009-03-01 14:15:09 +00:00
Daniel James d442f20bf8 Move some of the data structure classes out of hash table data.
[SVN r51409]
2009-02-22 23:50:20 +00:00
Daniel James d36fc98c15 Make copy_buckets and move_buckets member functions - so that calling them is a bit simpler.
[SVN r51408]
2009-02-22 23:50:04 +00:00
John Maddock 700c4717d6 Add PDF generation options to fix external links to point to the web site.
Added a few more Boostbook based libs that were missed first time around.
Fixed PDF naming issues.

[SVN r51284]
2009-02-17 10:05:58 +00:00
Daniel James 1e73578ab6 Don't copy images for the standalone hash and unordered documentation, was only
really required before the libraries were integrated into boost.

[SVN r51263]
2009-02-15 19:32:19 +00:00
Daniel James 971224a282 Use the new 'boost:' links for the hash, unordered and quickbook documentation.
[SVN r51262]
2009-02-15 19:32:04 +00:00
John Maddock acce19ce43 Add Jamfile to build PDF versions of all the docs.
Tweaked some existing Jamfiles so that PDF build finds all the necessary image files etc.
Tweaked fo.xsl to provide more options by default, and improve formatting.

[SVN r51104]
2009-02-08 16:59:14 +00:00
Daniel James 77021c5bbb Remove a tab.
[SVN r50452]
2009-01-03 23:26:00 +00:00
Daniel James fe3873b28f Add support for initializer lists to config and the unordered containers.
[SVN r50118]
2008-12-04 21:30:19 +00:00
Daniel James c1e9a6ac59 Workaround another in-place destruction.
[SVN r50029]
2008-11-29 21:47:55 +00:00
Daniel James c2425106ea Wild stab at getting destruction working on more compilers.
[SVN r49955]
2008-11-27 11:42:13 +00:00
Daniel James c8e7874534 Use aligned storage for the value.
[SVN r49927]
2008-11-24 23:15:55 +00:00
Daniel James 601daa0e5d Use a larger prime number list. Fixes #1710
[SVN r49926]
2008-11-24 22:56:04 +00:00
Daniel James d022cc48ad Document operator==/operator!= as undefined if the equality predicates aren't equivalent. Fixes #2237.
[SVN r49925]
2008-11-24 22:55:47 +00:00
Daniel James 527a72860d Extra tests for equality with different hash functions.
[SVN r49924]
2008-11-24 22:55:14 +00:00
Daniel James f0bb74a530 Use the new swap library.
[SVN r49770]
2008-11-15 13:07:29 +00:00
Daniel James b75f06d935 Use pragmas to suppress a Visual C++ warning.
[SVN r49756]
2008-11-14 16:11:16 +00:00
Daniel James e2d1d75955 Explicitly specify the template parameters in the unordered container friend, in order to avoid some warnings.
[SVN r49735]
2008-11-14 12:51:00 +00:00
Michael A. Jackson 80dc7b5e6a Updating dependency information for modularized libraries.
[SVN r49628]
2008-11-07 17:05:27 +00:00
Michael A. Jackson 1f4d8e7c21 Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
Michael A. Jackson 366c09f199 Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
John Maddock d98f72c4e1 Change includes of <cmath> to <boost/config/no_tr1/config.hpp>.
Previously if Boost.TR1 was in the include path then including <cmath> pulls in all the new TR1 math functions, which in turn also requires linking to an external library.  With auto-linking support this requires that library to have been built and be present in the library search path, even if the actual library under use is header only.

Fixes #2392.


[SVN r49254]
2008-10-10 16:10:00 +00:00
Daniel James e6417fe652 Update unordered changelog.
[SVN r48853]
2008-09-18 11:23:12 +00:00
Daniel James f5d52cc9b2 Move the unordered headers into the unordered directory.
[SVN r48803]
2008-09-16 21:49:41 +00:00
Daniel James 62427c8287 Forward headers for the unordered containers.
[SVN r48802]
2008-09-16 21:45:53 +00:00
Daniel James ab588fe872 Fix a workaround macro.
[SVN r48791]
2008-09-15 21:48:46 +00:00
Daniel James fe1385ab34 More recent version of the working draft.
[SVN r48082]
2008-08-11 07:53:05 +00:00
Daniel James d6f513be52 Rename 'emplace' with hint to 'emplace_hint'.
[SVN r48081]
2008-08-11 07:52:37 +00:00
Daniel James d8fa4cef60 Fix a link and a header.
[SVN r47881]
2008-07-30 09:44:26 +00:00
Daniel James 506f478ec7 Fix a typo.
[SVN r47813]
2008-07-25 21:25:58 +00:00
Daniel James f2c420e289 Remove some old information that's no longer true.
[SVN r47750]
2008-07-24 10:14:15 +00:00
Daniel James eae2a90463 Remove a mention of the hash functions which I missed before.
[SVN r47522]
2008-07-17 23:08:32 +00:00
Daniel James 4305d10264 On second thoughts, I'll just completely remove hash_value for ordered
containers. It's low quality and not very generic (it uses boost::hash for
mapped values). Should be a painless change.


[SVN r47465]
2008-07-15 22:03:15 +00:00
Daniel James d5b38b01fc Better hash function for unordered containers. Still a bit rubbish.
[SVN r47463]
2008-07-15 21:26:54 +00:00
Daniel James c49dbd782d Update the implementation details.
[SVN r47403]
2008-07-13 20:07:45 +00:00
Daniel James c7bde21be7 Note that emplace is only available on a few compilers.
[SVN r47402]
2008-07-13 19:42:56 +00:00
Daniel James d5fdc0b47e Update the docs for the new location of FNV-1.
[SVN r47146]
2008-07-06 21:29:47 +00:00
Daniel James c3d97bd613 I've only got one hash function for release, so no need for its own directory.
[SVN r47144]
2008-07-06 21:07:31 +00:00
Daniel James 2960390f79 Clean up the FNV-1 comments.
[SVN r47143]
2008-07-06 21:06:52 +00:00
Daniel James f723f857e4 'Bias' should be 'basis'.
[SVN r47132]
2008-07-06 12:41:09 +00:00
Daniel James d66936a640 Require explicit conversion from allocators.
(Not what it says in the draft standard, but I think that might be a defect).


[SVN r47085]
2008-07-04 22:57:20 +00:00
Daniel James 3640e1e96c Workaround for some template syntax not supported in old versions of Visual C++ 6.5
[SVN r47040]
2008-07-03 14:34:56 +00:00
Daniel James ec1e809fc3 Extract the hash and equality functions from hash_table_data_*.
As these are extensions and add extra requirements to the container elements,
they shouldn't be part of hash_table_data_* so that they won't get instantiated
if an unordered container is explicitly instantiated.

Merged revisions 46594-46604 via svnmerge from 
https://svn.boost.org/svn/boost/branches/unordered/trunk


[SVN r46607]
2008-06-22 13:54:45 +00:00
Daniel James 8868fa4687 Merge inspect fixes for the unordered library.
Merged revisions 46470-46592 via svnmerge from 
https://svn.boost.org/svn/boost/branches/unordered/trunk

................
  r46589 | danieljames | 2008-06-21 21:37:42 +0100 (Sat, 21 Jun 2008) | 2 lines
  
  Fix some inspect errors (tabs and missing copyright/license).
................
  r46591 | danieljames | 2008-06-21 21:47:51 +0100 (Sat, 21 Jun 2008) | 1 line
  
  Move memory.hpp into the helpers subdirectory.
................
  r46592 | danieljames | 2008-06-21 22:08:53 +0100 (Sat, 21 Jun 2008) | 1 line
  
  Prevent inspect errors for unnamed namespaces in some of the test header files.
................


[SVN r46594]
2008-06-21 22:02:15 +00:00
Daniel James ebd75b4010 Get the test to pass when pair's default constructor creates two instances of
the member classes.

With some standard libraries I was getting two copies of the object after
creating a default pair, probably because it was creating an instance for its
default parameter. So only test after creating the pair object - since it isn't
our concern how many instances that creates.


[SVN r46587]
2008-06-21 19:58:39 +00:00
Daniel James 9bd3f498a7 Define unordered containers' friend functions outside of the class.
On some compilers, friend functions are being instantiated when the main class
is explicitly instantiated. This is slightly problematic because the equality
functions (which are an extension) put extra requirements on the types used. So
I'm going to try defining the functions outside of the class, in the hope that
they won't get instantiated. If someone wants non-member functions to be
instantiated, I think it's reasonable to expect them to explicitly instantiate
them, especially as compilers don't seem to be consistent about this.


[SVN r46579]
2008-06-21 15:32:11 +00:00
Daniel James 659a014976 Fix in an error in the unordered containers' emulated move constructors. These
aren't actually used, so I could probalby just remove 'move_from' for now (it's
used in the full move library).


[SVN r46410]
2008-06-15 17:03:37 +00:00
Daniel James 885574e1bf Fix typo. Thanks to Thorsten.
Merged revisions 46112 via svnmerge from 
https://svn.boost.org/svn/boost/branches/unordered/trunk

........
  r46112 | danieljames | 2008-06-04 13:34:29 +0100 (Wed, 04 Jun 2008) | 1 line
  
  Fix copy and paste error in the max_load_factor documentation.
........


[SVN r46340]
2008-06-11 22:06:52 +00:00
81 changed files with 5759 additions and 3879 deletions
+1
View File
@@ -0,0 +1 @@
/doc/html/
+95 -1
View File
@@ -3,6 +3,9 @@
/ 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) ]
[template ticket[number]'''<ulink
url="https://svn.boost.org/trac/boost/ticket/'''[number]'''">'''#[number]'''</ulink>''']
[section:changes Change Log]
[h2 Review Version]
@@ -44,7 +47,7 @@ First official release.
[h2 Boost 1.38.0]
* Use [@boost:/libs/utility/swap.html `boost::swap`].
* Use [@boost:/libs/core/swap.html `boost::swap`].
* [@https://svn.boost.org/trac/boost/ticket/2237 Ticket 2237]:
Document that the equality and inequality operators are undefined for two
objects if their equality predicates aren't equivalent. Thanks to Daniel
@@ -175,4 +178,95 @@ C++11 support has resulted in some breaking changes:
* Fix warning due to accidental odd assignment.
* Slightly better error messages.
[h2 Boost 1.50.0]
* Fix equality for `unordered_multiset` and `unordered_multimap`.
* [@https://svn.boost.org/trac/boost/ticket/6857 Ticket 6857]:
Implement `reserve`.
* [@https://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
Avoid gcc's `-Wfloat-equal` warning.
* [@https://svn.boost.org/trac/boost/ticket/6784 Ticket 6784]:
Fix some Sun specific code.
* [@https://svn.boost.org/trac/boost/ticket/6190 Ticket 6190]:
Avoid gcc's `-Wshadow` warning.
* [@https://svn.boost.org/trac/boost/ticket/6905 Ticket 6905]:
Make namespaces in macros compatible with `bcp` custom namespaces.
Fixed by Luke Elliott.
* Remove some of the smaller prime number of buckets, as they may make
collisions quite probable (e.g. multiples of 5 are very common because
we used base 10).
* On old versions of Visual C++, use the container library's implementation
of `allocator_traits`, as it's more likely to work.
* On machines with 64 bit std::size_t, use power of 2 buckets, with Thomas
Wang's hash function to pick which one to use. As modulus is very slow
for 64 bit values.
* Some internal changes.
[h2 Boost 1.51.0]
* 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]).
* Updated to use the new config macros.
[h2 Boost 1.52.0]
* Faster assign, which assigns to existing nodes where possible, rather than
creating entirely new nodes and copy constructing.
* Fixed bug in `erase_range` ([ticket 7471]).
* Reverted some of the internal changes to how nodes are created, especially
for C++11 compilers. 'construct' and 'destroy' should work a little better
for C++11 allocators.
* Simplified the implementation a bit. Hopefully more robust.
[h2 Boost 1.53.0]
* Remove support for the old pre-standard variadic pair constructors, and
equality implementation. Both have been deprecated since Boost 1.48.
* Remove use of deprecated config macros.
* More internal implementation changes, including a much simpler
implementation of `erase`.
[h2 Boost 1.54.0]
* Mark methods specified in standard as `noexpect`. More to come in the next
release.
* If the hash function and equality predicate are known to both have nothrow
move assignment or construction then use them.
[h2 Boost 1.55.0]
* Avoid some warnings ([ticket 8851], [ticket 8874]).
* Avoid exposing some detail functions via. ADL on the iterators.
* Follow the standard by only using the allocators' construct and destroy
methods to construct and destroy stored elements. Don't use them for internal
data like pointers.
[h2 Boost 1.56.0]
* Fix some shadowed variable warnings ([ticket 9377]).
* Fix allocator use in documentation ([ticket 9719]).
* Always use prime number of buckets for integers. Fixes performance
regression when inserting consecutive integers, although makes other
uses slower ([ticket 9282]).
* Only construct elements using allocators, as specified in C++11 standard.
[h2 Boost 1.57.0]
* Fix the `pointer` typedef in iterators ([ticket 10672]).
* Fix Coverity warning
([@https://github.com/boostorg/unordered/pull/2 GitHub #2]).
[h2 Boost 1.58.0]
* Remove unnecessary template parameter from const iterators.
* Rename private `iterator` typedef in some iterator classes, as it
confuses some traits classes.
* Fix move assignment with stateful, propagate_on_container_move_assign
allocators ([ticket 10777]).
* Fix rare exception safety issue in move assignment.
* Fix potential overflow when calculating number of buckets to allocate
([@https://github.com/boostorg/unordered/pull/4 GitHub #4]).
[endsect]
+5 -4
View File
@@ -8,11 +8,12 @@
Support for move semantics is implemented using Boost.Move. If rvalue
references are available it will use them, but if not it uses a close,
but imperfect emulation. On such compilers you'll need to use Boost.Move
to take advantage of using movable container elements, also note that:
but imperfect emulation. On such compilers:
* Non-copyable objects can be stored in the containers, but without support
for rvalue references the container will not be movable.
* Non-copyable objects can be stored in the containers.
They can be constructed in place using `emplace`, or if they support
Boost.Move, moved into place.
* The containers themselves are not movable.
* Argument forwarding is not perfect.
[endsect]
+2 -2
View File
@@ -54,14 +54,14 @@ order to work with non-C++11 compilers and libraries.
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<Key> >
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class ``[classref boost::unordered_map unordered_map]``;
template<
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<Key> >
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class ``[classref boost::unordered_multimap unordered_multimap]``;
}
+13 -8
View File
@@ -3,7 +3,7 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[def __wang__
[@http://www.concentric.net/~Ttwang/tech/inthash.htm
[@http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm
Thomas Wang's article on integer hash functions]]
[section:rationale Implementation Rationale]
@@ -85,7 +85,8 @@ of 2.
Using a prime number of buckets, and choosing a bucket by using the modulus
of the hash function's result will usually give a good result. The downside
is that the required modulus operation is fairly expensive.
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.
@@ -95,12 +96,16 @@ functions this can't be relied on.
To avoid this a transformation could be applied to the hash function, for an
example see __wang__. Unfortunately, a transformation like Wang's requires
knowledge of the number of bits in the hash value, so it isn't portable enough.
This leaves more expensive methods, such as Knuth's Multiplicative Method
(mentioned in Wang's article). These don't tend to work as well as taking the
modulus of a prime, and the extra computation required might negate
efficiency advantage of power of 2 hash tables.
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.
So, this implementation uses a prime number for the hash table size.
Currently this is only done on 64 bit architecures, where prime number
modulus can be expensive. Although this varies depending on the architecture,
so I probably should revisit it.
I'm also thinking of introducing a mechanism whereby a hash function can
indicate that it's safe to be used directly with power of 2 buckets, in
which case a faster plain power of 2 implementation can be used.
[endsect]
+118 -17
View File
@@ -67,14 +67,20 @@ EOL;
<?php if ($map): ?>
<row>
<entry><emphasis>Key</emphasis></entry>
<entry>Key must be Assignable and CopyConstructible.</entry></row>
<entry><code>Key</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<row>
<entry><emphasis>Mapped</emphasis></entry>
<entry>Mapped must be CopyConstructible</entry></row>
<entry><code>Mapped</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<?php else: ?>
<row>
<entry><emphasis>Value</emphasis></entry>
<entry>Value must be Assignable and CopyConstructible</entry></row>
<entry><code>Value</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<?php endif ?>
<row>
<entry><emphasis>Hash</emphasis></entry>
@@ -206,6 +212,11 @@ EOL;
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
@@ -237,6 +248,11 @@ EOL;
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter>
@@ -408,6 +424,11 @@ EOL;
' if and only if there is no element in the container with an equivalent '.$key_name. '.';
?></para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<?php if ($equivalent_keys): ?>
<para>An iterator pointing to the inserted element.</para>
@@ -428,10 +449,6 @@ EOL;
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="emplace_hint">
@@ -453,6 +470,11 @@ EOL;
?></para>
<para><code>hint</code> is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<?php if ($equivalent_keys): ?>
<para>An iterator pointing to the inserted element.</para>
@@ -473,10 +495,6 @@ EOL;
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="insert">
@@ -490,6 +508,39 @@ EOL;
' if and only if there is no element in the container with an equivalent '.$key_name. '.';
?></para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<?php if ($equivalent_keys): ?>
<para>An iterator pointing to the inserted element.</para>
<?php else: ?>
<para>The bool component of the return type is true if an insert took place.</para>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent <?php echo $key_name; ?>.</para>
<?php endif; ?>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type><?php echo $equivalent_keys ? 'iterator' : 'std::pair&lt;iterator, bool&gt;' ?></type>
<description>
<para>Inserts <code>obj</code> in the container<?php
echo $equivalent_keys ? '.' :
' if and only if there is no element in the container with an equivalent '.$key_name. '.';
?></para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<?php if ($equivalent_keys): ?>
<para>An iterator pointing to the inserted element.</para>
@@ -522,6 +573,44 @@ EOL;
<?php endif; ?>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<?php if ($equivalent_keys): ?>
<para>An iterator pointing to the inserted element.</para>
<?php else: ?>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent <?php echo $key_name; ?>.</para>
<?php endif; ?>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same <?php echo $key_name; ?>. </para>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="hint">
<paramtype>const_iterator</paramtype>
</parameter>
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>iterator</type>
<description>
<?php if ($equivalent_keys): ?>
<para>Inserts <code>obj</code> in the container.</para>
<?php else: ?>
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.</para>
<?php endif; ?>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<?php if ($equivalent_keys): ?>
<para>An iterator pointing to the inserted element.</para>
@@ -553,6 +642,10 @@ EOL;
<description>
<para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent <?php echo $key_name; ?>.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>*first</code>.</para>
</requires>
<throws>
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
@@ -963,6 +1056,18 @@ EOL;
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
@@ -1001,9 +1106,7 @@ EOL;
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
@@ -1044,9 +1147,7 @@ EOL;
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
+392 -62
View File
@@ -29,7 +29,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<tbody>
<row>
<entry><emphasis>Value</emphasis></entry>
<entry>Value must be Assignable and CopyConstructible</entry></row>
<entry><code>Value</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<row>
<entry><emphasis>Hash</emphasis></entry>
<entry>A unary function object type that acts a hash function for a <code>Value</code>. It takes a single argument of type <code>Value</code> and returns a value of type std::size_t.</entry></row>
@@ -151,6 +153,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
@@ -182,6 +189,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter>
@@ -350,6 +362,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent value.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<para>The bool component of the return type is true if an insert took place.</para>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
@@ -366,10 +383,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="emplace_hint">
@@ -388,6 +401,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent value.</para>
<para><code>hint</code> is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
</returns>
@@ -404,10 +422,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="insert">
@@ -418,6 +432,32 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent value.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<para>The bool component of the return type is true if an insert took place.</para>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>std::pair&lt;iterator, bool&gt;</type>
<description>
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent value.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<para>The bool component of the return type is true if an insert took place.</para>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
@@ -442,6 +482,36 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent value.</para>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="hint">
<paramtype>const_iterator</paramtype>
</parameter>
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>iterator</type>
<description>
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent value.</para>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent value.</para>
</returns>
@@ -469,6 +539,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent value.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>*first</code>.</para>
</requires>
<throws>
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
@@ -846,6 +920,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
@@ -876,9 +962,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
@@ -911,9 +995,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
@@ -982,7 +1064,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<tbody>
<row>
<entry><emphasis>Value</emphasis></entry>
<entry>Value must be Assignable and CopyConstructible</entry></row>
<entry><code>Value</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<row>
<entry><emphasis>Hash</emphasis></entry>
<entry>A unary function object type that acts a hash function for a <code>Value</code>. It takes a single argument of type <code>Value</code> and returns a value of type std::size_t.</entry></row>
@@ -1104,6 +1188,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
@@ -1135,6 +1224,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter>
@@ -1303,6 +1397,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
@@ -1318,10 +1417,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="emplace_hint">
@@ -1340,6 +1435,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
<para><code>hint</code> is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
@@ -1356,10 +1456,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="insert">
@@ -1370,6 +1466,31 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts <code>obj</code> in the container.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>iterator</type>
<description>
<para>Inserts <code>obj</code> in the container.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
@@ -1393,6 +1514,36 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Inserts <code>obj</code> in the container.</para>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same value. </para>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="hint">
<paramtype>const_iterator</paramtype>
</parameter>
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>iterator</type>
<description>
<para>Inserts <code>obj</code> in the container.</para>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
@@ -1420,6 +1571,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent value.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>*first</code>.</para>
</requires>
<throws>
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
@@ -1797,6 +1952,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
@@ -1827,9 +1994,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
@@ -1862,9 +2027,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
@@ -1939,10 +2102,14 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<tbody>
<row>
<entry><emphasis>Key</emphasis></entry>
<entry>Key must be Assignable and CopyConstructible.</entry></row>
<entry><code>Key</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<row>
<entry><emphasis>Mapped</emphasis></entry>
<entry>Mapped must be CopyConstructible</entry></row>
<entry><code>Mapped</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<row>
<entry><emphasis>Hash</emphasis></entry>
<entry>A unary function object type that acts a hash function for a <code>Key</code>. It takes a single argument of type <code>Key</code> and returns a value of type std::size_t.</entry></row>
@@ -2067,6 +2234,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
@@ -2098,6 +2270,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter>
@@ -2266,6 +2443,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent key.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<para>The bool component of the return type is true if an insert took place.</para>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
@@ -2282,10 +2464,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="emplace_hint">
@@ -2304,6 +2482,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Inserts an object, constructed with the arguments <code>args</code>, in the container if and only if there is no element in the container with an equivalent key.</para>
<para><code>hint</code> is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
</returns>
@@ -2320,10 +2503,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="insert">
@@ -2334,6 +2513,32 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent key.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<para>The bool component of the return type is true if an insert took place.</para>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>std::pair&lt;iterator, bool&gt;</type>
<description>
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent key.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<para>The bool component of the return type is true if an insert took place.</para>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
@@ -2358,6 +2563,36 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent key.</para>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="hint">
<paramtype>const_iterator</paramtype>
</parameter>
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>iterator</type>
<description>
<para>Inserts <code>obj</code> in the container if and only if there is no element in the container with an equivalent key.</para>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<para>If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key.</para>
</returns>
@@ -2385,6 +2620,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>*first</code>.</para>
</requires>
<throws>
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
@@ -2793,6 +3032,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
@@ -2825,9 +3076,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
@@ -2862,9 +3111,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
@@ -2937,10 +3184,14 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<tbody>
<row>
<entry><emphasis>Key</emphasis></entry>
<entry>Key must be Assignable and CopyConstructible.</entry></row>
<entry><code>Key</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<row>
<entry><emphasis>Mapped</emphasis></entry>
<entry>Mapped must be CopyConstructible</entry></row>
<entry><code>Mapped</code> must be <code>Erasable</code> from the container
(i.e. <code>allocator_traits</code> can <code>destroy</code> it).
</entry></row>
<row>
<entry><emphasis>Hash</emphasis></entry>
<entry>A unary function object type that acts a hash function for a <code>Key</code>. It takes a single argument of type <code>Key</code> and returns a value of type std::size_t.</entry></row>
@@ -3065,6 +3316,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<template>
@@ -3096,6 +3352,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.</para>
</description>
<requires>
<para>If the defaults are used, <code>hasher</code>, <code>key_equal</code> and
<code>allocator_type</code> need to be <code>DefaultConstructible</code>.
</para>
</requires>
</constructor>
<constructor>
<parameter>
@@ -3264,6 +3525,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
@@ -3279,10 +3545,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="emplace_hint">
@@ -3301,6 +3563,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Inserts an object, constructed with the arguments <code>args</code>, in the container.</para>
<para><code>hint</code> is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>args</code>.
</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
@@ -3317,10 +3584,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Since existing <code>std::pair</code> implementations don't support
<code>std::piecewise_construct</code> this emulates it,
but using <code>boost::unordered::piecewise_construct</code>.</para>
<para>In version of Boost before 1.48 this emulated the variadic pair
constructor from older C++0x drafts. For backwards compatability
this can be enabled by defining the macro
<code>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT</code>.</para>
</notes>
</method>
<method name="insert">
@@ -3331,6 +3594,31 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts <code>obj</code> in the container.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>iterator</type>
<description>
<para>Inserts <code>obj</code> in the container.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
@@ -3354,6 +3642,36 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>Inserts <code>obj</code> in the container.</para>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>CopyInsertable</code>.</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
<throws>
<para>If an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
<notes>
<para>The standard is fairly vague on the meaning of the hint. But the only practical way to use it, and the only way that Boost.Unordered supports is to point to an existing element with the same key. </para>
<para>Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor.</para>
<para>Pointers and references to elements are never invalidated.</para>
</notes>
</method>
<method name="insert">
<parameter name="hint">
<paramtype>const_iterator</paramtype>
</parameter>
<parameter name="obj">
<paramtype>value_type&amp;&amp;</paramtype>
</parameter>
<type>iterator</type>
<description>
<para>Inserts <code>obj</code> in the container.</para>
<para>hint is a suggestion to where the element should be inserted.</para>
</description>
<requires>
<para><code>value_type</code> is <code>MoveInsertable</code>.</para>
</requires>
<returns>
<para>An iterator pointing to the inserted element.</para>
</returns>
@@ -3381,6 +3699,10 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<description>
<para>Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key.</para>
</description>
<requires>
<para><code>value_type</code> is <code>EmplaceConstructible</code> into
<code>X</code> from <code>*first</code>.</para>
</requires>
<throws>
<para>When inserting a single element, if an exception is thrown by an operation other than a call to <code>hasher</code> the function has no effect.</para>
</throws>
@@ -3758,6 +4080,18 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
<method name="reserve">
<parameter name="n">
<paramtype>size_type</paramtype>
</parameter>
<type>void</type>
<description>
<para>Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.</para>
</description>
<throws>
<para>The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.</para>
</throws>
</method>
</method-group>
<free-function-group name="Equality Comparisons">
<function name="operator==">
@@ -3790,9 +4124,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
@@ -3827,9 +4159,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
</description>
<notes>
<para>The behavior of this function was changed to match
the C++11 standard in Boost 1.48. If you wish to use
the old behaviour, define the macro
<code>BOOST_UNORDERED_DEPRECATED_EQUALITY</code>.</para>
the C++11 standard in Boost 1.48.</para>
<para>Behavior is undefined if the two containers don't have
equivalent equality predicates.</para>
</notes>
File diff suppressed because it is too large Load Diff
@@ -1,523 +0,0 @@
// Copyright 2005-2011 Daniel James.
// Copyright 2009 Pablo Halpern.
//
// 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)
//
// Allocator traits written by Daniel James based on Pablo Halpern's
// implementation.
#ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/detail/select_type.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/enum.hpp>
#include <boost/limits.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
#define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
#endif
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
# include <memory>
#endif
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
# include <type_traits>
#endif
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// Integral_constrant, true_type, false_type
//
// Uses the standard versions if available.
#if !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
using std::integral_constant;
using std::true_type;
using std::false_type;
#else
template <typename T, T Value>
struct integral_constant { enum { value = Value }; };
typedef boost::unordered::detail::integral_constant<bool, true> true_type;
typedef boost::unordered::detail::integral_constant<bool, false> false_type;
#endif
////////////////////////////////////////////////////////////////////////////
// Explicitly call a destructor
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
template <class T>
inline void destroy(T* x) {
x->~T();
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
////////////////////////////////////////////////////////////////////////////
// Bits and pieces for implementing traits
//
// Some of these are also used elsewhere
template <typename T> typename boost::add_lvalue_reference<T>::type make();
struct choice9 { typedef char (&type)[9]; };
struct choice8 : choice9 { typedef char (&type)[8]; };
struct choice7 : choice8 { typedef char (&type)[7]; };
struct choice6 : choice7 { typedef char (&type)[6]; };
struct choice5 : choice6 { typedef char (&type)[5]; };
struct choice4 : choice5 { typedef char (&type)[4]; };
struct choice3 : choice4 { typedef char (&type)[3]; };
struct choice2 : choice3 { typedef char (&type)[2]; };
struct choice1 : choice2 { typedef char (&type)[1]; };
choice1 choose();
typedef choice1::type yes_type;
typedef choice2::type no_type;
struct private_type
{
private_type const &operator,(int) const;
};
template <typename T>
no_type is_private_type(T const&);
yes_type is_private_type(private_type const&);
struct convert_from_anything {
template <typename T>
convert_from_anything(T const&);
};
#if !defined(BOOST_NO_SFINAE_EXPR)
# define BOOST_UNORDERED_HAVE_CALL_DETECTION 1
template <typename T, unsigned int> struct expr_test;
template <typename T> struct expr_test<T, sizeof(char)> : T {};
template <typename U> static char for_expr_test(U const&);
#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
template <typename U> \
static typename boost::unordered::detail::expr_test< \
BOOST_PP_CAT(choice, result), \
sizeof(boost::unordered::detail::for_expr_test(( \
(expression), \
0)))>::type test( \
BOOST_PP_CAT(choice, count))
#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
template <typename U> \
static BOOST_PP_CAT(choice, result)::type test( \
BOOST_PP_CAT(choice, count))
#define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
struct BOOST_PP_CAT(has_, name) \
{ \
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
boost::unordered::detail::make< thing >().name args); \
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
\
enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
}
#else
# define BOOST_UNORDERED_HAVE_CALL_DETECTION 0
template <typename T> struct identity { typedef T type; };
#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
\
typedef typename boost::unordered::detail::identity<member>::type \
BOOST_PP_CAT(check, count); \
\
template <BOOST_PP_CAT(check, count) e> \
struct BOOST_PP_CAT(test, count) { \
typedef BOOST_PP_CAT(choice, result) type; \
}; \
\
template <class U> static typename \
BOOST_PP_CAT(test, count)<&U::name>::type \
test(BOOST_PP_CAT(choice, count))
#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
template <class U> static BOOST_PP_CAT(choice, result)::type \
test(BOOST_PP_CAT(choice, count))
#define BOOST_UNORDERED_HAS_MEMBER(name) \
struct BOOST_PP_CAT(has_, name) \
{ \
struct impl { \
struct base_mixin { int name; }; \
struct base : public T, public base_mixin {}; \
\
BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
\
enum { value = sizeof(choice2::type) == \
sizeof(test<base>(choose())) \
}; \
}; \
\
enum { value = impl::value }; \
}
#endif
////////////////////////////////////////////////////////////////////////////
// Allocator traits
//
// Uses the standard versions if available.
// (although untested as I don't have access to a standard version yet)
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
template <typename Alloc>
struct allocator_traits : std::allocator_traits<Alloc> {};
template <typename Alloc, typename T>
struct rebind_wrap
{
typedef typename std::allocator_traits<Alloc>::
template rebind_alloc<T> type;
};
#else
// TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
template <typename Alloc, typename T>
struct rebind_wrap
{
typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type;
};
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
template <typename Tp, typename Default> \
struct default_type_ ## tname { \
\
template <typename X> \
static choice1::type test(choice1, typename X::tname* = 0); \
\
template <typename X> \
static choice2::type test(choice2, void* = 0); \
\
struct DefaultWrap { typedef Default tname; }; \
\
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
\
typedef typename boost::detail::if_true<value>:: \
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
::type::tname type; \
}
#else
template <typename T, typename T2>
struct sfinae : T2 {};
#define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
template <typename Tp, typename Default> \
struct default_type_ ## tname { \
\
template <typename X> \
static typename boost::unordered::detail::sfinae< \
typename X::tname, choice1>::type \
test(choice1); \
\
template <typename X> \
static choice2::type test(choice2); \
\
struct DefaultWrap { typedef Default tname; }; \
\
enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
\
typedef typename boost::detail::if_true<value>:: \
BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
::type::tname type; \
}
#endif
#define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
typename default_type_ ## tname<T, arg>::type
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
#if BOOST_UNORDERED_HAVE_CALL_DETECTION
template <typename T>
BOOST_UNORDERED_HAS_FUNCTION(
select_on_container_copy_construction, U const, (), 0
);
template <typename T>
BOOST_UNORDERED_HAS_FUNCTION(
max_size, U const, (), 0
);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_FUNCTION(
construct, U, (
boost::unordered::detail::make<ValueType*>(),
boost::unordered::detail::make<ValueType const>()), 2
);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_FUNCTION(
destroy, U, (boost::unordered::detail::make<ValueType*>()), 1
);
#else
template <typename T>
BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
template <typename T>
BOOST_UNORDERED_HAS_MEMBER(max_size);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_MEMBER(construct);
template <typename T, typename ValueType>
BOOST_UNORDERED_HAS_MEMBER(destroy);
#endif
template <typename Alloc>
inline typename boost::enable_if_c<
boost::unordered::detail::
has_select_on_container_copy_construction<Alloc>::value, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
{
return rhs.select_on_container_copy_construction();
}
template <typename Alloc>
inline typename boost::disable_if_c<
boost::unordered::detail::
has_select_on_container_copy_construction<Alloc>::value, Alloc
>::type call_select_on_container_copy_construction(const Alloc& rhs)
{
return rhs;
}
template <typename SizeType, typename Alloc>
inline typename boost::enable_if_c<
boost::unordered::detail::has_max_size<Alloc>::value, SizeType
>::type call_max_size(const Alloc& a)
{
return a.max_size();
}
template <typename SizeType, typename Alloc>
inline typename boost::disable_if_c<
boost::unordered::detail::has_max_size<Alloc>::value, SizeType
>::type call_max_size(const Alloc&)
{
return (std::numeric_limits<SizeType>::max)();
}
template <typename Alloc>
struct allocator_traits
{
typedef Alloc allocator_type;
typedef typename Alloc::value_type value_type;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
pointer;
template <typename T>
struct pointer_to_other : boost::pointer_to_other<pointer, T> {};
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
typename pointer_to_other<const value_type>::type)
const_pointer;
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
// typename pointer_to_other<void>::type)
// void_pointer;
//
//typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
// typename pointer_to_other<const void>::type)
// const_void_pointer;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
std::ptrdiff_t) difference_type;
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
size_type;
// TODO: rebind_alloc and rebind_traits
static pointer allocate(Alloc& a, size_type n)
{ return a.allocate(n); }
// I never use this, so I'll just comment it out for now.
//
//static pointer allocate(Alloc& a, size_type n,
// const_void_pointer hint)
// { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
static void deallocate(Alloc& a, pointer p, size_type n)
{ a.deallocate(p, n); }
public:
// Only supporting the basic copy constructor for now.
template <typename T>
static typename boost::enable_if_c<
boost::unordered::detail::has_construct<Alloc, T>::value>::type
construct(Alloc& a, T* p, T const& x)
{
a.construct(p, x);
}
template <typename T>
static typename boost::disable_if_c<
boost::unordered::detail::has_construct<Alloc, T>::value>::type
construct(Alloc&, T* p, T const& x)
{
new ((void*) p) T(x);
}
template <typename T>
static typename boost::enable_if_c<
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc& a, T* p)
{
a.destroy(p);
}
template <typename T>
static typename boost::disable_if_c<
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p)
{
boost::unordered::detail::destroy(p);
}
static size_type max_size(const Alloc& a)
{
return boost::unordered::detail::call_max_size<size_type>(a);
}
// Allocator propagation on construction
static Alloc select_on_container_copy_construction(Alloc const& rhs)
{
return boost::unordered::detail::
call_select_on_container_copy_construction(rhs);
}
// Allocator propagation on assignment and swap.
// Return true if lhs is modified.
typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc, propagate_on_container_copy_assignment, false_type)
propagate_on_container_copy_assignment;
typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc,propagate_on_container_move_assignment, false_type)
propagate_on_container_move_assignment;
typedef BOOST_UNORDERED_DEFAULT_TYPE(
Alloc,propagate_on_container_swap,false_type)
propagate_on_container_swap;
};
#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
#undef BOOST_UNORDERED_DEFAULT_TYPE
#endif
// array_constructor
//
// Allocate and construct an array in an exception safe manner, and
// clean up if an exception is thrown before the container takes charge
// of it.
template <typename Allocator>
struct array_constructor
{
typedef boost::unordered::detail::allocator_traits<Allocator> traits;
typedef typename traits::pointer pointer;
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
{
constructed_ = pointer();
ptr_ = pointer();
}
~array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
traits::destroy(alloc_, boost::addressof(*p));
traits::deallocate(alloc_, ptr_, length_);
}
}
template <typename V>
void construct(V const& v, std::size_t l)
{
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = traits::allocate(alloc_, length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
traits::construct(alloc_, boost::addressof(*constructed_), v);
}
pointer get() const
{
return ptr_;
}
pointer release()
{
pointer p(ptr_);
ptr_ = pointer();
return p;
}
private:
array_constructor(array_constructor const&);
array_constructor& operator=(array_constructor const&);
};
}}}
#endif
File diff suppressed because it is too large Load Diff
@@ -1,480 +0,0 @@
// Copyright (C) 2011 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)
// See http://www.boost.org/libs/unordered for documentation
#ifndef BOOST_UNORDERED_EMPLACE_ARGS_HPP
#define BOOST_UNORDERED_EMPLACE_ARGS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/move/move.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/dec.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/tuple/tuple.hpp>
#include <utility>
#if !defined(BOOST_NO_0X_HDR_TUPLE)
#include <tuple>
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4512) // assignment operator could not be generated.
#pragma warning(disable:4345) // behavior change: an object of POD type
// constructed with an initializer of the form ()
// will be default-initialized.
#endif
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
!defined(BOOST_NO_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_VARIADIC_MOVE
#endif
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// emplace_args
//
// Either forwarding variadic arguments, or storing the arguments in
// emplace_args##n
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
#define BOOST_UNORDERED_EMPLACE_ARGS Args&&... args
#define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
#else
#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
#define BOOST_UNORDERED_EMPLACE_FORWARD args
#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
boost::forward<BOOST_PP_CAT(A,i)>(BOOST_PP_CAT(a,i))
#define BOOST_UNORDERED_EARGS(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
struct BOOST_PP_CAT(emplace_args, n) \
{ \
BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
BOOST_PP_CAT(emplace_args, n) ( \
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, a) \
) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
{} \
\
}; \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
inline BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
> create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
BOOST_PP_CAT(emplace_args, n) < \
BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
> e(BOOST_PP_ENUM_PARAMS_Z(z, n, a)); \
return e; \
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)( \
boost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(a, n)))
#else
#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
BOOST_PP_CAT(Arg, n); \
BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
BOOST_PP_CAT(a, n)(BOOST_PP_CAT(a, n))
#endif
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
_)
#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
#undef BOOST_UNORDERED_EARGS_MEMBER
#undef BOOST_UNORDERED_EARGS_INIT
#endif
////////////////////////////////////////////////////////////////////////////
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
// e.g. for int
#if !defined(BOOST_NO_RVALUE_REFERENCES)
# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
#else
struct please_ignore_this_overload {
typedef please_ignore_this_overload type;
};
template <typename T>
struct rv_ref_impl {
typedef BOOST_RV_REF(T) type;
};
template <typename T>
struct rv_ref :
boost::detail::if_true<
boost::is_class<T>::value
>::BOOST_NESTED_TEMPLATE then <
boost::unordered::detail::rv_ref_impl<T>,
please_ignore_this_overload
>::type
{};
# define BOOST_UNORDERED_RV_REF(T) \
typename boost::unordered::detail::rv_ref<T>::type
#endif
////////////////////////////////////////////////////////////////////////////
// Construct from tuple
//
// Used for piecewise construction.
#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590)
#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
template<typename T> \
void construct_from_tuple(T* ptr, namespace_::tuple<>) \
{ \
new ((void*) ptr) T(); \
} \
\
BOOST_PP_REPEAT_FROM_TO(1, n, \
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
void construct_from_tuple(T* ptr, \
namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
new ((void*) ptr) T( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
); \
}
#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
namespace_::get<n>(x)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost)
#if !defined(BOOST_NO_0X_HDR_TUPLE)
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std)
#endif
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
#undef BOOST_UNORDERED_GET_TUPLE_ARG
#else
template <int N> struct length {};
template<typename T>
void construct_from_tuple_impl(
boost::unordered::detail::length<0>, T* ptr,
boost::tuple<>)
{
new ((void*) ptr) T();
}
#define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, _) \
template<typename T, BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
void construct_from_tuple_impl( \
boost::unordered::detail::length<n>, T* ptr, \
namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
new ((void*) ptr) T( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
); \
}
#define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, _) \
boost::get<n>(x)
BOOST_PP_REPEAT_FROM_TO(1, 10, \
BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, _)
template <typename T, typename Tuple>
void construct_from_tuple(T* ptr, Tuple const& x)
{
construct_from_tuple_impl(
boost::unordered::detail::length<
boost::tuples::length<Tuple>::value>(),
ptr, x);
}
#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
#undef BOOST_UNORDERED_GET_TUPLE_ARG
#endif
////////////////////////////////////////////////////////////////////////////
// SFINAE traits for construction.
// Decide which construction method to use for a three argument
// call. Note that this is difficult to do using overloads because
// the arguments are packed into 'emplace_args3'.
//
// The decision is made on the first argument.
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
struct emulation1 {
static choice1::type test(choice1, std::pair<A, B> const&);
static choice2::type test(choice2, A const&);
static choice3::type test(choice3, convert_from_anything const&);
enum { value =
sizeof(test(choose(), boost::unordered::detail::make<A0>())) ==
sizeof(choice2::type) };
};
#endif
template <typename A, typename B, typename A0>
struct check3_base {
static choice1::type test(choice1,
boost::unordered::piecewise_construct_t);
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
static choice2::type test(choice2, A const&);
#endif
static choice3::type test(choice3, ...);
enum { value =
sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
};
template <typename A, typename B, typename A0>
struct piecewise3 {
enum { value = check3_base<A,B,A0>::value == sizeof(choice1::type) };
};
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
struct emulation3 {
enum { value = check3_base<A,B,A0>::value == sizeof(choice2::type) };
};
#endif
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
////////////////////////////////////////////////////////////////////////////
// Construct from variadic parameters
template <typename T, typename... Args>
inline void construct_impl(T* address, Args&&... args)
{
new((void*) address) T(boost::forward<Args>(args)...);
}
template <typename A, typename B, typename A0, typename A1, typename A2>
inline typename enable_if<piecewise3<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address, A0&&, A1&& a1, A2&& a2)
{
boost::unordered::detail::construct_from_tuple(
boost::addressof(address->first), a1);
boost::unordered::detail::construct_from_tuple(
boost::addressof(address->second), a2);
}
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
inline typename enable_if<emulation1<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address, A0&& a0)
{
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B();
}
template <typename A, typename B, typename A0, typename A1, typename A2>
inline typename enable_if<emulation3<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address, A0&& a0, A1&& a1, A2&& a2)
{
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B(
boost::forward<A1>(a1),
boost::forward<A2>(a2));
}
template <typename A, typename B,
typename A0, typename A1, typename A2, typename A3,
typename... Args>
inline void construct_impl(std::pair<A, B>* address,
A0&& a0, A1&& a1, A2&& a2, A3&& a3, Args&&... args)
{
new((void*) boost::addressof(address->first)) A(boost::forward<A0>(a0));
new((void*) boost::addressof(address->second)) B(
boost::forward<A1>(a1),
boost::forward<A2>(a2),
boost::forward<A3>(a3),
boost::forward<Args>(args)...);
}
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
#else // BOOST_UNORDERED_VARIADIC_MOVE
////////////////////////////////////////////////////////////////////////////////
// Construct from emplace_args
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
template < \
typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
inline void construct_impl(T* address, \
boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
{ \
new((void*) address) T( \
BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
args.a)); \
}
template <typename T, typename A0>
inline void construct_impl(T* address, emplace_args1<A0> const& args)
{
new((void*) address) T(boost::forward<A0>(args.a0));
}
template <typename T, typename A0, typename A1>
inline void construct_impl(T* address, emplace_args2<A0, A1> const& args)
{
new((void*) address) T(
boost::forward<A0>(args.a0),
boost::forward<A1>(args.a1)
);
}
template <typename T, typename A0, typename A1, typename A2>
inline void construct_impl(T* address, emplace_args3<A0, A1, A2> const& args)
{
new((void*) address) T(
boost::forward<A0>(args.a0),
boost::forward<A1>(args.a1),
boost::forward<A2>(args.a2)
);
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
template <typename A, typename B, typename A0, typename A1, typename A2>
inline typename enable_if<piecewise3<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address,
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
{
boost::unordered::detail::construct_from_tuple(
boost::addressof(address->first), args.a1);
boost::unordered::detail::construct_from_tuple(
boost::addressof(address->second), args.a2);
}
#if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
template <typename A, typename B, typename A0>
inline typename enable_if<emulation1<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address,
boost::unordered::detail::emplace_args1<A0> const& args)
{
new((void*) boost::addressof(address->first)) A(
boost::forward<A0>(args.a0));
new((void*) boost::addressof(address->second)) B();
}
template <typename A, typename B, typename A0, typename A1, typename A2>
inline typename enable_if<emulation3<A, B, A0>, void>::type
construct_impl(std::pair<A, B>* address,
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args)
{
new((void*) boost::addressof(address->first)) A(
boost::forward<A0>(args.a0));
new((void*) boost::addressof(address->second)) B(
boost::forward<A1>(args.a1),
boost::forward<A2>(args.a2));
}
#define BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(z, num_params, _) \
template <typename A, typename B, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
inline void construct_impl(std::pair<A, B>* address, \
boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
{ \
new((void*) boost::addressof(address->first)) A( \
boost::forward<A0>(args.a0)); \
new((void*) boost::addressof(address->second)) B( \
BOOST_PP_ENUM_##z(BOOST_PP_DEC(num_params), \
BOOST_UNORDERED_CALL_FORWARD2, args.a)); \
}
#define BOOST_UNORDERED_CALL_FORWARD2(z, i, a) \
BOOST_UNORDERED_CALL_FORWARD(z, BOOST_PP_INC(i), a)
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL(1, 2, _)
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_PAIR_IMPL
#undef BOOST_UNORDERED_CALL_FORWARD2
#endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
#endif // BOOST_UNORDERED_VARIADIC_MOVE
////////////////////////////////////////////////////////////////////////////
// Construct without using the emplace args mechanism.
template <typename T, typename A0>
inline void construct_impl2(T* address, BOOST_FWD_REF(A0) a0)
{
new((void*) address) T(
boost::forward<A0>(a0)
);
}
}}}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif
+217 -360
View File
@@ -7,12 +7,12 @@
#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/emplace_args.hpp>
#include <boost/unordered/detail/extract_key.hpp>
namespace boost { namespace unordered { namespace detail {
@@ -26,10 +26,13 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, grouped_node<A, T> >::type::pointer link_pointer;
A, grouped_node<A, T> >::type allocator;
typedef typename ::boost::unordered::detail::
allocator_traits<allocator>::pointer node_pointer;
typedef node_pointer link_pointer;
link_pointer next_;
link_pointer group_prev_;
node_pointer group_prev_;
std::size_t hash_;
grouped_node() :
@@ -38,22 +41,27 @@ namespace boost { namespace unordered { namespace detail {
hash_(0)
{}
void init(link_pointer self)
void init(node_pointer self)
{
group_prev_ = self;
}
private:
grouped_node& operator=(grouped_node const&);
};
template <typename T>
struct grouped_ptr_node :
boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
typedef T value_type;
typedef boost::unordered::detail::ptr_bucket bucket_base;
typedef grouped_ptr_node<T>* node_pointer;
typedef ptr_bucket* link_pointer;
link_pointer group_prev_;
node_pointer group_prev_;
std::size_t hash_;
boost::unordered::detail::value_base<T> value_base_;
grouped_ptr_node() :
bucket_base(),
@@ -61,10 +69,17 @@ namespace boost { namespace unordered { namespace detail {
hash_(0)
{}
void init(link_pointer self)
void init(node_pointer self)
{
group_prev_ = self;
}
void* address() { return value_base_.address(); }
value_type& value() { return value_base_.value(); }
value_type* value_ptr() { return value_base_.value_ptr(); }
private:
grouped_ptr_node& operator=(grouped_ptr_node const&);
};
// If the allocator uses raw pointers use grouped_ptr_node
@@ -120,22 +135,23 @@ namespace boost { namespace unordered { namespace detail {
{
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
@@ -143,16 +159,15 @@ namespace boost { namespace unordered { namespace detail {
{
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_grouped_node<allocator, value_type> pick;
typedef boost::unordered::detail::pick_grouped_node<allocator,
value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
@@ -160,6 +175,8 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
};
template <typename Types>
@@ -168,19 +185,19 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::table<Types> table;
typedef typename table::value_type value_type;
typedef typename table::bucket bucket;
typedef typename table::buckets buckets;
typedef typename table::policy policy;
typedef typename table::node_pointer node_pointer;
typedef typename table::node_allocator node_allocator;
typedef typename table::node_allocator_traits node_allocator_traits;
typedef typename table::bucket_pointer bucket_pointer;
typedef typename table::link_pointer link_pointer;
typedef typename table::previous_pointer previous_pointer;
typedef typename table::hasher hasher;
typedef typename table::key_equal key_equal;
typedef typename table::key_type key_type;
typedef typename table::node_constructor node_constructor;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
// Constructors
@@ -193,12 +210,17 @@ namespace boost { namespace unordered { namespace detail {
grouped_table_impl(grouped_table_impl const& x)
: table(x, node_allocator_traits::
select_on_container_copy_construction(x.node_alloc())) {}
select_on_container_copy_construction(x.node_alloc()))
{
this->init(x);
}
grouped_table_impl(grouped_table_impl const& x,
node_allocator const& a)
: table(x, a)
{}
{
this->init(x);
}
grouped_table_impl(grouped_table_impl& x,
boost::unordered::detail::move_tag m)
@@ -209,64 +231,62 @@ namespace boost { namespace unordered { namespace detail {
node_allocator const& a,
boost::unordered::detail::move_tag m)
: table(x, a, m)
{}
{
this->move_init(x);
}
// Accessors
template <class Key, class Pred>
node_pointer find_node_impl(
std::size_t hash,
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = hash % this->bucket_count_;
node_pointer n = this->get_start(bucket_index);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
iterator n = this->begin(bucket_index);
for (;;)
{
if (!n) return n;
if (!n.node_) return n;
std::size_t node_hash = n->hash_;
if (hash == node_hash)
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(n->value())))
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (node_hash % this->bucket_count_ != bucket_index)
return node_pointer();
if (this->hash_to_bucket(node_hash) != bucket_index)
return iterator();
}
n = static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_);
n = iterator(n.node_->group_prev_->next_);
}
}
std::size_t count(key_type const& k) const
{
node_pointer n = this->find_node(k);
if (!n) return 0;
iterator n = this->find_node(k);
if (!n.node_) return 0;
std::size_t count = 0;
node_pointer it = n;
std::size_t x = 0;
node_pointer it = n.node_;
do {
it = static_cast<node_pointer>(it->group_prev_);
++count;
} while(it != n);
it = it->group_prev_;
++x;
} while(it != n.node_);
return count;
return x;
}
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
node_pointer n = this->find_node(k);
iterator n = this->find_node(k);
return std::make_pair(
iterator(n), iterator(n ?
static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_) :
n));
n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
}
// Equality
@@ -274,16 +294,13 @@ namespace boost { namespace unordered { namespace detail {
bool equals(grouped_table_impl const& other) const
{
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
for(node_pointer n1 = this->get_start(); n1;)
for(iterator n1 = this->begin(); n1.node_;)
{
node_pointer n2 = other.find_matching_node(n1);
if (!n2) return false;
node_pointer end1 = static_cast<node_pointer>(
static_cast<node_pointer>(n1->group_prev_)->next_);
node_pointer end2 = static_cast<node_pointer>(
static_cast<node_pointer>(n2->group_prev_)->next_);
iterator n2 = other.find_matching_node(n1);
if (!n2.node_) return false;
iterator end1(n1.node_->group_prev_->next_);
iterator end2(n2.node_->group_prev_->next_);
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
@@ -291,27 +308,24 @@ namespace boost { namespace unordered { namespace detail {
return true;
}
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
static bool group_equals(node_pointer n1, node_pointer end1,
node_pointer n2, node_pointer end2)
static bool group_equals(iterator n1, iterator end1,
iterator n2, iterator end2)
{
for(;;)
{
if (n1->value() != n2->value())
break;
if (*n1 != *n2) break;
n1 = static_cast<node_pointer>(n1->next_);
n2 = static_cast<node_pointer>(n2->next_);
++n1;
++n2;
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
for(node_pointer n1a = n1, n2a = n2;;)
for(iterator n1a = n1, n2a = n2;;)
{
n1a = static_cast<node_pointer>(n1a->next_);
n2a = static_cast<node_pointer>(n2a->next_);
++n1a;
++n2a;
if (n1a == end1)
{
@@ -322,151 +336,137 @@ namespace boost { namespace unordered { namespace detail {
if (n2a == end2) return false;
}
node_pointer start = n1;
for(;n1 != end2; n1 = static_cast<node_pointer>(n1->next_))
iterator start = n1;
for(;n1 != end1; ++n1)
{
value_type const& v = n1->value();
value_type const& v = *n1;
if (find(start, n1, v)) continue;
std::size_t matches = count_equal(n2, end2, v);
if (!matches || matches != 1 + count_equal(
static_cast<node_pointer>(n1->next_), end1, v))
return false;
if (!matches) return false;
iterator next = n1;
++next;
if (matches != 1 + count_equal(next, end1, v)) return false;
}
return true;
}
static bool find(node_pointer n, node_pointer end, value_type const& v)
static bool find(iterator n, iterator end, value_type const& v)
{
for(;n != end; n = static_cast<node_pointer>(n->next_))
if (n->value() == v)
for(;n != end; ++n)
if (*n == v)
return true;
return false;
}
static std::size_t count_equal(node_pointer n, node_pointer end,
static std::size_t count_equal(iterator n, iterator end,
value_type const& v)
{
std::size_t count = 0;
for(;n != end; n = static_cast<node_pointer>(n->next_))
if (n->value() == v) ++count;
for(;n != end; ++n)
if (*n == v) ++count;
return count;
}
#else
static bool group_equals(node_pointer n1, node_pointer end1,
node_pointer n2, node_pointer end2)
{
for(;;)
{
if(!extractor::compare_mapped(
n1->value(), n2->value()))
return false;
n1 = static_cast<node_pointer>(n1->next_);
n2 = static_cast<node_pointer>(n2->next_);
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
}
#endif
// Emplace/Insert
static inline void add_after_node(
node_pointer n,
node_pointer pos)
{
n->next_ = static_cast<node_pointer>(pos->group_prev_)->next_;
n->next_ = pos->group_prev_->next_;
n->group_prev_ = pos->group_prev_;
static_cast<node_pointer>(pos->group_prev_)->next_ =
static_cast<link_pointer>(n);
pos->group_prev_ = static_cast<link_pointer>(n);
pos->group_prev_->next_ = n;
pos->group_prev_ = n;
}
inline node_pointer add_node(
inline iterator add_node(
node_constructor& a,
std::size_t hash,
node_pointer pos)
std::size_t key_hash,
iterator pos)
{
node_pointer n = a.release();
n->hash_ = hash;
if(pos) {
this->add_after_node(n, pos);
n->hash_ = key_hash;
if (pos.node_) {
this->add_after_node(n, pos.node_);
if (n->next_) {
std::size_t next_bucket =
static_cast<node_pointer>(n->next_)->hash_ %
this->bucket_count_;
if (next_bucket != hash % this->bucket_count_) {
std::size_t next_bucket = this->hash_to_bucket(
static_cast<node_pointer>(n->next_)->hash_);
if (next_bucket != this->hash_to_bucket(key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
}
else {
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
bucket_pointer b = this->get_bucket(
this->hash_to_bucket(key_hash));
if (!b->next_)
{
previous_pointer start_node = this->get_previous_start();
link_pointer start_node = this->get_previous_start();
if (start_node->next_) {
this->get_bucket(
this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_
% this->bucket_count_)->next_ = n;
))->next_ = n;
}
b->next_ = start_node;
n->next_ = start_node->next_;
start_node->next_ = static_cast<link_pointer>(n);
start_node->next_ = n;
}
else
{
n->next_ = b->next_->next_;
b->next_->next_ = static_cast<link_pointer>(n);
b->next_->next_ = n;
}
}
++this->size_;
return n;
return iterator(n);
}
node_pointer emplace_impl(node_constructor& a)
iterator emplace_impl(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t hash = this->hash_function()(k);
node_pointer position = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return this->add_node(a, hash, position);
return this->add_node(a, key_hash, position);
}
void emplace_impl_no_rehash(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t hash = this->hash_function()(k);
this->add_node(a, hash,
this->find_node(hash, k));
std::size_t key_hash = this->hash(k);
this->add_node(a, key_hash, this->find_node(key_hash, k));
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
iterator emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
}
# else
iterator emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
# endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor a(this->node_alloc());
a.construct_node();
a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return iterator(emplace_impl(a));
}
@@ -485,8 +485,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t distance = boost::unordered::detail::distance(i, j);
if(distance == 1) {
node_constructor a(this->node_alloc());
a.construct_node();
a.construct_value2(*i);
a.construct_with_value2(*i);
emplace_impl(a);
}
else {
@@ -495,8 +494,7 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
a.construct_node();
a.construct_value2(*i);
a.construct_with_value2(*i);
emplace_impl_no_rehash(a);
}
}
@@ -508,8 +506,7 @@ namespace boost { namespace unordered { namespace detail {
{
node_constructor a(this->node_alloc());
for (; i != j; ++i) {
a.construct_node();
a.construct_value2(*i);
a.construct_with_value2(*i);
emplace_impl(a);
}
}
@@ -523,11 +520,9 @@ namespace boost { namespace unordered { namespace detail {
{
if(!this->size_) return 0;
std::size_t hash = this->hash_function()(k);
std::size_t bucket_index = hash % this->bucket_count_;
bucket_pointer bucket = this->get_bucket(bucket_index);
previous_pointer prev = bucket->next_;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
for (;;)
@@ -535,240 +530,117 @@ namespace boost { namespace unordered { namespace detail {
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (node_hash % this->bucket_count_ != bucket_index)
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == hash &&
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
prev = static_cast<previous_pointer>(
static_cast<node_pointer>(prev->next_)->group_prev_);
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
}
node_pointer pos = static_cast<node_pointer>(prev->next_);
link_pointer end1 =
static_cast<node_pointer>(pos->group_prev_)->next_;
node_pointer end = static_cast<node_pointer>(end1);
prev->next_ = end1;
this->fix_buckets(bucket, prev, end);
return this->delete_nodes(pos, end);
node_pointer first_node = static_cast<node_pointer>(prev->next_);
link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
}
node_pointer erase(node_pointer r)
iterator erase(c_iterator r)
{
BOOST_ASSERT(r);
node_pointer next = static_cast<node_pointer>(r->next_);
bucket_pointer bucket = this->get_bucket(
r->hash_ % this->bucket_count_);
previous_pointer prev = unlink_node(*bucket, r);
this->fix_buckets(bucket, prev, next);
this->delete_node(r);
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
erase_nodes(r.node_, next.node_);
return next;
}
node_pointer erase_range(node_pointer r1, node_pointer r2)
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2) return r2;
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
previous_pointer prev = unlink_nodes(
*this->get_bucket(bucket_index), r1, r2);
this->fix_buckets_range(bucket_index, prev, r1, r2);
this->delete_nodes(r1, r2);
return r2;
if (r1 == r2) return iterator(r2.node_);
erase_nodes(r1.node_, r2.node_);
return iterator(r2.node_);
}
static previous_pointer unlink_node(bucket& b, node_pointer n)
link_pointer erase_nodes(node_pointer i, node_pointer j)
{
node_pointer next = static_cast<node_pointer>(n->next_);
previous_pointer prev =
static_cast<previous_pointer>(n->group_prev_);
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
if(prev->next_ != n) {
// The node is at the beginning of a group.
// Split the groups containing 'i' and 'j'.
// And get the pointer to the node before i while
// we're at it.
link_pointer prev = split_groups(i, j);
// Find the previous node pointer:
prev = b.next_;
while(prev->next_ != n) {
prev = static_cast<previous_pointer>(
static_cast<node_pointer>(prev->next_)->group_prev_);
}
// Remove from group
if (next && next->group_prev_ == static_cast<link_pointer>(n))
{
next->group_prev_ = n->group_prev_;
}
}
else if (next && next->group_prev_ == static_cast<link_pointer>(n))
{
// The deleted node is not at the end of the group, so
// change the link from the next node.
next->group_prev_ = n->group_prev_;
}
else {
// The deleted node is at the end of the group, so the
// first node in the group is pointing to it.
// Find that to change its pointer.
node_pointer x = static_cast<node_pointer>(n->group_prev_);
while(x->group_prev_ != static_cast<link_pointer>(n)) {
x = static_cast<node_pointer>(x->group_prev_);
}
x->group_prev_ = n->group_prev_;
// If we don't have a 'prev' it means that i is at the
// beginning of a block, so search through the blocks in the
// same bucket.
if (!prev) {
prev = this->get_previous_start(bucket_index);
while (prev->next_ != i)
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
}
prev->next_ = static_cast<link_pointer>(next);
return prev;
}
static previous_pointer unlink_nodes(bucket& b,
node_pointer begin, node_pointer end)
{
previous_pointer prev = static_cast<previous_pointer>(
begin->group_prev_);
if(prev->next_ != static_cast<link_pointer>(begin)) {
// The node is at the beginning of a group.
// Find the previous node pointer:
prev = b.next_;
while(prev->next_ != static_cast<link_pointer>(begin))
prev = static_cast<previous_pointer>(
static_cast<node_pointer>(prev->next_)->group_prev_);
if (end) split_group(end);
}
else {
node_pointer group1 = split_group(begin);
if (end) {
node_pointer group2 = split_group(end);
if(begin == group2) {
link_pointer end1 = group1->group_prev_;
link_pointer end2 = group2->group_prev_;
group1->group_prev_ = end2;
group2->group_prev_ = end1;
}
}
}
prev->next_ = static_cast<link_pointer>(end);
// Delete the nodes.
do {
link_pointer group_end =
static_cast<node_pointer>(prev->next_)->group_prev_->next_;
this->delete_nodes(prev, group_end);
bucket_index = this->fix_bucket(bucket_index, prev);
} while(prev->next_ != j);
return prev;
}
// Break a ciruclar list into two, with split as the beginning
// of the second group (if split is at the beginning then don't
// split).
static node_pointer split_group(node_pointer split)
static link_pointer split_groups(node_pointer i, node_pointer j)
{
// Find first node in group.
node_pointer first = split;
while (static_cast<node_pointer>(first->group_prev_)->next_ ==
static_cast<link_pointer>(first))
first = static_cast<node_pointer>(first->group_prev_);
node_pointer prev = i->group_prev_;
if (prev->next_ != i) prev = node_pointer();
if(first == split) return split;
link_pointer last = first->group_prev_;
first->group_prev_ = split->group_prev_;
split->group_prev_ = last;
return first;
}
////////////////////////////////////////////////////////////////////////
// copy_buckets_to
//
// Basic exception safety. If an exception is thrown this will
// leave dst partially filled and the buckets unset.
static void copy_buckets_to(buckets const& src, buckets& dst)
{
BOOST_ASSERT(!dst.buckets_);
dst.create_buckets();
node_constructor a(dst.node_alloc());
node_pointer n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n) {
std::size_t hash = n->hash_;
node_pointer group_end =
static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_);
a.construct_node();
a.construct_value2(n->value());
node_pointer first_node = a.release();
node_pointer end = first_node;
first_node->hash_ = hash;
prev->next_ = static_cast<link_pointer>(first_node);
++dst.size_;
for(n = static_cast<node_pointer>(n->next_); n != group_end;
n = static_cast<node_pointer>(n->next_))
{
a.construct_node();
a.construct_value2(n->value());
end = a.release();
end->hash_ = hash;
add_after_node(end, first_node);
++dst.size_;
if (j) {
node_pointer first = j;
while (first != i && first->group_prev_->next_ == first) {
first = first->group_prev_;
}
prev = place_in_bucket(dst, prev, end);
boost::swap(first->group_prev_, j->group_prev_);
if (first == i) return prev;
}
if (prev) {
node_pointer first = prev;
while (first->group_prev_->next_ == first) {
first = first->group_prev_;
}
boost::swap(first->group_prev_, i->group_prev_);
}
return prev;
}
////////////////////////////////////////////////////////////////////////
// move_buckets_to
//
// Basic exception safety. The source nodes are left in an unusable
// state if an exception throws.
// fill_buckets
static void move_buckets_to(buckets& src, buckets& dst)
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
BOOST_ASSERT(!dst.buckets_);
link_pointer prev = dst.get_previous_start();
dst.create_buckets();
while (n.node_) {
std::size_t key_hash = n.node_->hash_;
iterator group_end(n.node_->group_prev_->next_);
node_constructor a(dst.node_alloc());
node_pointer n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n) {
std::size_t hash = n->hash_;
node_pointer group_end =
static_cast<node_pointer>(
static_cast<node_pointer>(n->group_prev_)->next_);
a.construct_node();
a.construct_value2(boost::move(n->value()));
node_pointer first_node = a.release();
node_pointer first_node = creator.create(*n);
node_pointer end = first_node;
first_node->hash_ = hash;
prev->next_ = static_cast<link_pointer>(first_node);
first_node->hash_ = key_hash;
prev->next_ = first_node;
++dst.size_;
for(n = static_cast<node_pointer>(n->next_); n != group_end;
n = static_cast<node_pointer>(n->next_))
for (++n; n != group_end; ++n)
{
a.construct_node();
a.construct_value2(boost::move(n->value()));
end = a.release();
end->hash_ = hash;
end = creator.create(*n);
end->hash_ = key_hash;
add_after_node(end, first_node);
++dst.size_;
}
@@ -780,40 +652,25 @@ namespace boost { namespace unordered { namespace detail {
// strong otherwise exception safety
void rehash_impl(std::size_t num_buckets)
{
BOOST_ASSERT(this->size_);
BOOST_ASSERT(this->buckets_);
buckets dst(this->node_alloc(), num_buckets);
dst.create_buckets();
previous_pointer src_start = this->get_previous_start();
previous_pointer dst_start = dst.get_previous_start();
dst_start->next_ = src_start->next_;
src_start->next_ = link_pointer();
dst.size_ = this->size_;
this->size_ = 0;
previous_pointer prev = dst_start;
this->create_buckets(num_buckets);
link_pointer prev = this->get_previous_start();
while (prev->next_)
prev = place_in_bucket(dst, prev,
static_cast<node_pointer>(
static_cast<node_pointer>(prev->next_)->group_prev_));
// Swap the new nodes back into the container and setup the
// variables.
dst.swap(*this); // no throw
prev = place_in_bucket(*this, prev,
static_cast<node_pointer>(prev->next_)->group_prev_);
}
// Iterate through the nodes placing them in the correct buckets.
// pre: prev->next_ is not null.
static previous_pointer place_in_bucket(buckets& dst,
previous_pointer prev, node_pointer end)
static link_pointer place_in_bucket(table& dst,
link_pointer prev, node_pointer end)
{
bucket_pointer b = dst.get_bucket(end->hash_ % dst.bucket_count_);
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(end->hash_));
if (!b->next_) {
b->next_ = static_cast<node_pointer>(prev);
return static_cast<previous_pointer>(end);
b->next_ = prev;
return end;
}
else {
link_pointer next = end->next_;
+32 -50
View File
@@ -6,6 +6,11 @@
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
namespace boost {
@@ -56,30 +61,25 @@ namespace detail {
return no_key();
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
template <class Arg>
static no_key extract(Arg const&)
{
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class Arg1, class Arg2, class... Args>
static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
{
return no_key();
}
#else
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
return no_key();
}
#endif
static bool compare_mapped(value_type const&, value_type const&)
{
return true;
}
};
template <class Key, class ValueType>
@@ -93,11 +93,6 @@ namespace detail {
return v.first;
}
static key_type const& extract(key_type const& v)
{
return v;
}
template <class Second>
static key_type const& extract(std::pair<key_type, Second> const& v)
{
@@ -111,21 +106,6 @@ namespace detail {
return v.first;
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
template <class Arg1, class... Args>
static key_type const& extract(key_type const& k,
Arg1 const&, Args const&...)
{
return k;
}
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
template <class Arg1>
static key_type const& extract(key_type const& k, Arg1 const&)
{
@@ -143,19 +123,27 @@ namespace detail {
return no_key();
}
template <class Arg, class Arg1>
static no_key extract(Arg const&, Arg1 const&)
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class Arg1, class Arg2, class Arg3, class... Args>
static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
Args const&...)
{
return no_key();
}
#endif
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
template <typename T2> \
static no_key extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<> const&, T2&&) \
namespace_ tuple<> const&, T2 const&) \
{ \
return no_key(); \
} \
@@ -163,17 +151,17 @@ namespace detail {
template <typename T, typename T2> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<T> const& k, T2&&) \
namespace_ tuple<T> const& k, T2 const&) \
{ \
return typename is_key<key_type, T>::type( \
namespace_::get<0>(k)); \
namespace_ get<0>(k)); \
}
#else
#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \
static no_key extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<> const&) \
namespace_ tuple<> const&) \
{ \
return no_key(); \
} \
@@ -181,25 +169,19 @@ namespace detail {
template <typename T> \
static typename is_key<key_type, T>::type \
extract(boost::unordered::piecewise_construct_t, \
namespace_::tuple<T> const& k) \
namespace_ tuple<T> const& k) \
{ \
return typename is_key<key_type, T>::type( \
namespace_::get<0>(k)); \
namespace_ get<0>(k)); \
}
#endif
BOOST_UNORDERED_KEY_FROM_TUPLE(boost)
BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
#if !defined(BOOST_NO_0X_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std)
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
#endif
static bool compare_mapped(value_type const& x, value_type const& y)
{
return x.second == y.second;
}
};
}}}
+3 -33
View File
@@ -6,45 +6,15 @@
#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
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;
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 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 = boost::hash<T>,
class P = std::equal_to<T>,
class A = std::allocator<T> >
class unordered_multiset;
struct piecewise_construct_t {};
const piecewise_construct_t piecewise_construct = piecewise_construct_t();
}
File diff suppressed because it is too large Load Diff
+168 -248
View File
@@ -7,60 +7,75 @@
#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/emplace_args.hpp>
#include <boost/unordered/detail/extract_key.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
namespace boost { namespace unordered { namespace detail {
template <typename A, typename T> struct node;
template <typename A, typename T> struct unique_node;
template <typename T> struct ptr_node;
template <typename Types> struct table_impl;
template <typename A, typename T>
struct node :
struct unique_node :
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, node<A, T> >::type::pointer link_pointer;
A, unique_node<A, T> >::type allocator;
typedef typename ::boost::unordered::detail::
allocator_traits<allocator>::pointer node_pointer;
typedef node_pointer link_pointer;
link_pointer next_;
std::size_t hash_;
node() :
unique_node() :
next_(),
hash_(0)
{}
void init(link_pointer)
void init(node_pointer)
{
}
private:
unique_node& operator=(unique_node const&);
};
template <typename T>
struct ptr_node :
boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
typedef T value_type;
typedef boost::unordered::detail::ptr_bucket bucket_base;
typedef ptr_node<T>* node_pointer;
typedef ptr_bucket* link_pointer;
std::size_t hash_;
boost::unordered::detail::value_base<T> value_base_;
ptr_node() :
bucket_base(),
hash_(0)
{}
void init(link_pointer)
void init(node_pointer)
{
}
void* address() { return value_base_.address(); }
value_type& value() { return value_base_.value(); }
value_type* value_ptr() { return value_base_.value_ptr(); }
private:
ptr_node& operator=(ptr_node const&);
};
// If the allocator uses raw pointers use ptr_node
@@ -69,7 +84,7 @@ namespace boost { namespace unordered { namespace detail {
template <typename A, typename T, typename NodePtr, typename BucketPtr>
struct pick_node2
{
typedef boost::unordered::detail::node<A, T> node;
typedef boost::unordered::detail::unique_node<A, T> node;
typedef typename boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap<A, node>::type
@@ -116,14 +131,12 @@ namespace boost { namespace unordered { namespace detail {
{
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef A allocator;
typedef T value_type;
typedef H hasher;
typedef P key_equal;
typedef T key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
@@ -132,6 +145,8 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
@@ -139,15 +154,14 @@ namespace boost { namespace unordered { namespace detail {
{
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef A allocator;
typedef std::pair<K const, M> value_type;
typedef H hasher;
typedef P key_equal;
typedef K key_type;
typedef typename boost::unordered::detail::rebind_wrap<
A, value_type>::type allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
typedef boost::unordered::detail::allocator_traits<allocator>
traits;
typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
@@ -156,6 +170,8 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
};
template <typename Types>
@@ -164,19 +180,19 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::table<Types> table;
typedef typename table::value_type value_type;
typedef typename table::bucket bucket;
typedef typename table::buckets buckets;
typedef typename table::policy policy;
typedef typename table::node_pointer node_pointer;
typedef typename table::node_allocator node_allocator;
typedef typename table::node_allocator_traits node_allocator_traits;
typedef typename table::bucket_pointer bucket_pointer;
typedef typename table::link_pointer link_pointer;
typedef typename table::previous_pointer previous_pointer;
typedef typename table::hasher hasher;
typedef typename table::key_equal key_equal;
typedef typename table::key_type key_type;
typedef typename table::node_constructor node_constructor;
typedef typename table::extractor extractor;
typedef typename table::iterator iterator;
typedef typename table::c_iterator c_iterator;
typedef std::pair<iterator, bool> emplace_return;
@@ -191,12 +207,17 @@ namespace boost { namespace unordered { namespace detail {
table_impl(table_impl const& x)
: table(x, node_allocator_traits::
select_on_container_copy_construction(x.node_alloc())) {}
select_on_container_copy_construction(x.node_alloc()))
{
this->init(x);
}
table_impl(table_impl const& x,
node_allocator const& a)
: table(x, a)
{}
{
this->init(x);
}
table_impl(table_impl& x,
boost::unordered::detail::move_tag m)
@@ -207,49 +228,51 @@ namespace boost { namespace unordered { namespace detail {
node_allocator const& a,
boost::unordered::detail::move_tag m)
: table(x, a, m)
{}
{
this->move_init(x);
}
// Accessors
template <class Key, class Pred>
node_pointer find_node_impl(
std::size_t hash,
iterator find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = hash % this->bucket_count_;
node_pointer n = this->get_start(bucket_index);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
iterator n = this->begin(bucket_index);
for (;;)
{
if (!n) return n;
if (!n.node_) return n;
std::size_t node_hash = n->hash_;
if (hash == node_hash)
std::size_t node_hash = n.node_->hash_;
if (key_hash == node_hash)
{
if (eq(k, this->get_key(n->value())))
if (eq(k, this->get_key(*n)))
return n;
}
else
{
if (node_hash % this->bucket_count_ != bucket_index)
return node_pointer();
if (this->hash_to_bucket(node_hash) != bucket_index)
return iterator();
}
n = static_cast<node_pointer>(n->next_);
++n;
}
}
std::size_t count(key_type const& k) const
{
return this->find_node(k) ? 1 : 0;
return this->find_node(k).node_ ? 1 : 0;
}
value_type& at(key_type const& k) const
{
if (this->size_) {
node_pointer it = this->find_node(k);
if (it) return it->value();
iterator it = this->find_node(k);
if (it.node_) return *it;
}
boost::throw_exception(
@@ -259,9 +282,10 @@ namespace boost { namespace unordered { namespace detail {
std::pair<iterator, iterator>
equal_range(key_type const& k) const
{
node_pointer n = this->find_node(k);
return std::make_pair(iterator(n),
iterator(n ? static_cast<node_pointer>(n->next_) : n));
iterator n = this->find_node(k);
iterator n2 = n;
if (n2.node_) ++n2;
return std::make_pair(n, n2);
}
// equals
@@ -269,21 +293,13 @@ namespace boost { namespace unordered { namespace detail {
bool equals(table_impl const& other) const
{
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
for(node_pointer n1 = this->get_start(); n1;
n1 = static_cast<node_pointer>(n1->next_))
for(iterator n1 = this->begin(); n1.node_; ++n1)
{
node_pointer n2 = other.find_matching_node(n1);
iterator n2 = other.find_matching_node(n1);
#if !defined(BOOST_UNORDERED_DEPRECATED_EQUALITY)
if(!n2 || n1->value() != n2->value())
if (!n2.node_ || *n1 != *n2)
return false;
#else
if(!n2 || !extractor::compare_mapped(
n1->value(), n2->value()))
return false;
#endif
}
return true;
@@ -291,84 +307,83 @@ namespace boost { namespace unordered { namespace detail {
// Emplace/Insert
inline node_pointer add_node(
inline iterator add_node(
node_constructor& a,
std::size_t hash)
std::size_t key_hash)
{
node_pointer n = a.release();
n->hash_ = hash;
n->hash_ = key_hash;
bucket_pointer b = this->get_bucket(hash % this->bucket_count_);
bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
if (!b->next_)
{
previous_pointer start_node = this->get_previous_start();
link_pointer start_node = this->get_previous_start();
if (start_node->next_) {
this->get_bucket(
static_cast<node_pointer>(start_node->next_)->hash_ %
this->bucket_count_)->next_ = n;
this->get_bucket(this->hash_to_bucket(
static_cast<node_pointer>(start_node->next_)->hash_)
)->next_ = n;
}
b->next_ = start_node;
n->next_ = start_node->next_;
start_node->next_ = static_cast<link_pointer>(n);
start_node->next_ = n;
}
else
{
n->next_ = b->next_->next_;
b->next_->next_ = static_cast<link_pointer>(n);
b->next_->next_ = n;
}
++this->size_;
return n;
return iterator(n);
}
value_type& operator[](key_type const& k)
{
typedef typename value_type::second_type mapped_type;
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
if (pos) return pos->value();
if (pos.node_) return *pos;
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_node();
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
a.construct_value(boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple());
#else
a.construct_value(
boost::unordered::detail::create_emplace_args(
boost::unordered::piecewise_construct,
boost::make_tuple(k),
boost::make_tuple()));
#endif
a.construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS3(
boost::unordered::piecewise_construct,
boost::make_tuple(k),
boost::make_tuple()));
this->reserve_for_insert(this->size_ + 1);
return add_node(a, hash)->value();
return *add_node(a, key_hash);
}
#if defined(BOOST_NO_RVALUE_REFERENCES)
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
emplace_return emplace(boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return emplace_return(iterator(this->begin()), false);
return emplace_return(this->begin(), false);
}
# else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
}
# endif
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
return emplace_impl(
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
#else
return emplace_impl(
extractor::extract(args.a0, args.a1),
@@ -376,7 +391,7 @@ namespace boost { namespace unordered { namespace detail {
#endif
}
#if !defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename A0>
emplace_return emplace(
boost::unordered::detail::emplace_args1<A0> const& args)
@@ -389,35 +404,34 @@ namespace boost { namespace unordered { namespace detail {
emplace_return emplace_impl(key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos) return emplace_return(iterator(pos), false);
if (pos.node_) return emplace_return(pos, false);
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(this->node_alloc());
a.construct_node();
a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(iterator(this->add_node(a, hash)), true);
return emplace_return(this->add_node(a, key_hash), true);
}
emplace_return emplace_impl_with_node(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos) return emplace_return(iterator(pos), false);
if (pos.node_) return emplace_return(pos, false);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
this->reserve_for_insert(this->size_ + 1);
return emplace_return(iterator(this->add_node(a, hash)), true);
return emplace_return(this->add_node(a, key_hash), true);
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
@@ -426,8 +440,7 @@ namespace boost { namespace unordered { namespace detail {
// Don't have a key, so construct the node first in order
// to be able to lookup the position.
node_constructor a(this->node_alloc());
a.construct_node();
a.construct_value(BOOST_UNORDERED_EMPLACE_FORWARD);
a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
return emplace_impl_with_node(a);
}
@@ -449,14 +462,9 @@ namespace boost { namespace unordered { namespace detail {
{
node_constructor a(this->node_alloc());
// Special case for empty buckets so that we can use
// max_load_ (which isn't valid when buckets_ is null).
if (!this->buckets_) {
insert_range_empty(a, k, i, j);
if (++i == j) return;
}
insert_range_impl2(a, k, i, j);
do {
while(++i != j) {
// Note: can't use get_key as '*i' might not be value_type - it
// could be a pair with first_types as key_type without const or
// a different second_type.
@@ -466,19 +474,7 @@ namespace boost { namespace unordered { namespace detail {
// be less efficient if copying the full value_type is
// expensive.
insert_range_impl2(a, extractor::extract(*i), i, j);
} while(++i != j);
}
template <class InputIt>
void insert_range_empty(node_constructor& a, key_type const& k,
InputIt i, InputIt j)
{
std::size_t hash = this->hash_function()(k);
a.construct_node();
a.construct_value2(*i);
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
this->add_node(a, hash);
}
}
template <class InputIt>
@@ -486,19 +482,17 @@ namespace boost { namespace unordered { namespace detail {
InputIt i, InputIt j)
{
// No side effects in this initial code
std::size_t hash = this->hash_function()(k);
node_pointer pos = this->find_node(hash, k);
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (!pos) {
a.construct_node();
a.construct_value2(*i);
if(this->size_ + 1 >= this->max_load_)
if (!pos.node_) {
a.construct_with_value2(*i);
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
boost::unordered::detail::insert_size(i, j));
// Nothing after this point can throw.
this->add_node(a, hash);
this->add_node(a, key_hash);
}
}
@@ -508,8 +502,7 @@ namespace boost { namespace unordered { namespace detail {
node_constructor a(this->node_alloc());
do {
a.construct_node();
a.construct_value2(*i);
a.construct_with_value2(*i);
emplace_impl_with_node(a);
} while(++i != j);
}
@@ -523,11 +516,9 @@ namespace boost { namespace unordered { namespace detail {
{
if(!this->size_) return 0;
std::size_t hash = this->hash_function()(k);
std::size_t bucket_index = hash % this->bucket_count_;
bucket_pointer bucket = this->get_bucket(bucket_index);
previous_pointer prev = bucket->next_;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
for (;;)
@@ -535,124 +526,68 @@ namespace boost { namespace unordered { namespace detail {
if (!prev->next_) return 0;
std::size_t node_hash =
static_cast<node_pointer>(prev->next_)->hash_;
if (node_hash % this->bucket_count_ != bucket_index)
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == hash &&
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
static_cast<node_pointer>(prev->next_)->value())))
break;
prev = static_cast<previous_pointer>(prev->next_);
prev = prev->next_;
}
node_pointer pos = static_cast<node_pointer>(prev->next_);
node_pointer end = static_cast<node_pointer>(pos->next_);
prev->next_ = pos->next_;
this->fix_buckets(bucket, prev, end);
return this->delete_nodes(pos, end);
link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
}
node_pointer erase(node_pointer r)
iterator erase(c_iterator r)
{
BOOST_ASSERT(r);
node_pointer next = static_cast<node_pointer>(r->next_);
bucket_pointer bucket = this->get_bucket(
r->hash_ % this->bucket_count_);
previous_pointer prev = unlink_node(*bucket, r);
this->fix_buckets(bucket, prev, next);
this->delete_node(r);
BOOST_ASSERT(r.node_);
iterator next(r.node_);
++next;
erase_nodes(r.node_, next.node_);
return next;
}
node_pointer erase_range(node_pointer r1, node_pointer r2)
iterator erase_range(c_iterator r1, c_iterator r2)
{
if (r1 == r2) return r2;
std::size_t bucket_index = r1->hash_ % this->bucket_count_;
previous_pointer prev = unlink_nodes(
*this->get_bucket(bucket_index), r1, r2);
this->fix_buckets_range(bucket_index, prev, r1, r2);
this->delete_nodes(r1, r2);
return r2;
if (r1 == r2) return iterator(r2.node_);
erase_nodes(r1.node_, r2.node_);
return iterator(r2.node_);
}
static previous_pointer unlink_node(bucket& b, node_pointer n)
void erase_nodes(node_pointer i, node_pointer j)
{
return unlink_nodes(b, n, static_cast<node_pointer>(n->next_));
}
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
static previous_pointer unlink_nodes(bucket& b,
node_pointer begin, node_pointer end)
{
previous_pointer prev = b.next_;
link_pointer begin_void = static_cast<link_pointer>(begin);
while(prev->next_ != begin_void)
prev = static_cast<previous_pointer>(prev->next_);
prev->next_ = static_cast<link_pointer>(end);
return prev;
// Find the node before i.
link_pointer prev = this->get_previous_start(bucket_index);
while(prev->next_ != i) prev = prev->next_;
// Delete the nodes.
do {
this->delete_node(prev);
bucket_index = this->fix_bucket(bucket_index, prev);
} while (prev->next_ != j);
}
////////////////////////////////////////////////////////////////////////
// copy_buckets_to
//
// Basic exception safety. If an exception is thrown this will
// leave dst partially filled and the buckets unset.
// fill_buckets
static void copy_buckets_to(buckets const& src, buckets& dst)
template <class NodeCreator>
static void fill_buckets(iterator n, table& dst,
NodeCreator& creator)
{
BOOST_ASSERT(!dst.buckets_);
link_pointer prev = dst.get_previous_start();
dst.create_buckets();
node_constructor a(dst.node_alloc());
node_pointer n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n) {
a.construct_node();
a.construct_value2(n->value());
node_pointer node = a.release();
node->hash_ = n->hash_;
prev->next_ = static_cast<link_pointer>(node);
while (n.node_) {
node_pointer node = creator.create(*n);
node->hash_ = n.node_->hash_;
prev->next_ = node;
++dst.size_;
n = static_cast<node_pointer>(n->next_);
prev = place_in_bucket(dst, prev);
}
}
////////////////////////////////////////////////////////////////////////
// move_buckets_to
//
// Basic exception safety. The source nodes are left in an unusable
// state if an exception throws.
static void move_buckets_to(buckets& src, buckets& dst)
{
BOOST_ASSERT(!dst.buckets_);
dst.create_buckets();
node_constructor a(dst.node_alloc());
node_pointer n = src.get_start();
previous_pointer prev = dst.get_previous_start();
while(n) {
a.construct_node();
a.construct_value2(boost::move(n->value()));
node_pointer node = a.release();
node->hash_ = n->hash_;
prev->next_ = static_cast<link_pointer>(node);
++dst.size_;
n = static_cast<node_pointer>(n->next_);
++n;
prev = place_in_bucket(dst, prev);
}
@@ -661,44 +596,29 @@ namespace boost { namespace unordered { namespace detail {
// strong otherwise exception safety
void rehash_impl(std::size_t num_buckets)
{
BOOST_ASSERT(this->size_);
BOOST_ASSERT(this->buckets_);
buckets dst(this->node_alloc(), num_buckets);
dst.create_buckets();
previous_pointer src_start = this->get_previous_start();
previous_pointer dst_start = dst.get_previous_start();
dst_start->next_ = src_start->next_;
src_start->next_ = link_pointer();
dst.size_ = this->size_;
this->size_ = 0;
previous_pointer prev = dst.get_previous_start();
this->create_buckets(num_buckets);
link_pointer prev = this->get_previous_start();
while (prev->next_)
prev = place_in_bucket(dst, prev);
// Swap the new nodes back into the container and setup the
// variables.
dst.swap(*this); // no throw
prev = place_in_bucket(*this, prev);
}
// Iterate through the nodes placing them in the correct buckets.
// pre: prev->next_ is not null.
static previous_pointer place_in_bucket(buckets& dst,
previous_pointer prev)
static link_pointer place_in_bucket(table& dst, link_pointer prev)
{
node_pointer n = static_cast<node_pointer>(prev->next_);
bucket_pointer b = dst.get_bucket(n->hash_ % dst.bucket_count_);
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
if (!b->next_) {
b->next_ = prev;
return static_cast<previous_pointer>(n);
return n;
}
else {
prev->next_ = n->next_;
n->next_ = b->next_->next_;
b->next_->next_ = static_cast<link_pointer>(n);
b->next_->next_ = n;
return prev;
}
}
+9 -3
View File
@@ -7,8 +7,9 @@
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/type_traits/is_convertible.hpp>
@@ -28,6 +29,11 @@ namespace boost { namespace unordered { namespace detail {
struct move_tag {};
struct empty_emplace {};
namespace func {
template <class T>
inline void ignore_unused_variable_warning(T const&) {}
}
////////////////////////////////////////////////////////////////////////////
// iterator SFINAE
@@ -56,7 +62,7 @@ namespace boost { namespace unordered { namespace detail {
// primes
#define BOOST_UNORDERED_PRIMES \
(5ul)(11ul)(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
(1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
(49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
+118 -108
View File
@@ -9,19 +9,19 @@
#ifndef BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/unordered_map_fwd.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#include <initializer_list>
#endif
@@ -57,7 +57,6 @@ namespace unordered
private:
typedef boost::unordered::detail::map<A, K, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
@@ -119,21 +118,23 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map(BOOST_RV_REF(unordered_map) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map(
std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
@@ -144,7 +145,7 @@ namespace unordered
// Destructor
~unordered_map();
~unordered_map() BOOST_NOEXCEPT;
// Assign
@@ -167,7 +168,7 @@ namespace unordered
return *this;
}
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map& operator=(unordered_map&& x)
{
table_.move_assign(x.table_);
@@ -176,72 +177,72 @@ namespace unordered
#endif
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_NOEXCEPT
{
return table_.node_alloc();
}
// size and capacity
bool empty() const
bool empty() const BOOST_NOEXCEPT
{
return table_.size_ == 0;
}
size_type size() const
size_type size() const BOOST_NOEXCEPT
{
return table_.size_;
}
size_type max_size() const;
size_type max_size() const BOOST_NOEXCEPT;
// iterators
iterator begin()
iterator begin() BOOST_NOEXCEPT
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const
const_iterator begin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end()
iterator end() BOOST_NOEXCEPT
{
return iterator();
}
const_iterator end() const
const_iterator end() const BOOST_NOEXCEPT
{
return const_iterator();
}
const_iterator cbegin() const
const_iterator cbegin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const
const_iterator cend() const BOOST_NOEXCEPT
{
return const_iterator();
}
// emplace
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args)
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...).first;
}
@@ -401,7 +402,7 @@ namespace unordered
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
@@ -451,12 +452,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const
size_type bucket_count() const BOOST_NOEXCEPT
{
return table_.bucket_count_;
}
size_type max_bucket_count() const
size_type max_bucket_count() const BOOST_NOEXCEPT
{
return table_.max_bucket_count();
}
@@ -465,21 +466,19 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table_.hash_function()(k) % table_.bucket_count_;
return table_.hash_to_bucket(table_.hash(k));
}
local_iterator begin(size_type n)
{
return table_.size_ ? local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
local_iterator();
return local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator begin(size_type n) const
{
return table_.size_ ? const_local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
const_local_iterator();
return const_local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
local_iterator end(size_type)
@@ -494,9 +493,8 @@ namespace unordered
const_local_iterator cbegin(size_type n) const
{
return table_.size_ ? const_local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
const_local_iterator();
return const_local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator cend(size_type) const
@@ -506,14 +504,15 @@ namespace unordered
// hash policy
float max_load_factor() const
float max_load_factor() const BOOST_NOEXCEPT
{
return table_.mlf_;
}
float load_factor() const;
void max_load_factor(float);
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<K,T,H,P,A>(
@@ -541,7 +540,6 @@ namespace unordered
private:
typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
@@ -603,21 +601,23 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap(
std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
@@ -628,7 +628,7 @@ namespace unordered
// Destructor
~unordered_multimap();
~unordered_multimap() BOOST_NOEXCEPT;
// Assign
@@ -652,7 +652,7 @@ namespace unordered
return *this;
}
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap& operator=(unordered_multimap&& x)
{
table_.move_assign(x.table_);
@@ -661,72 +661,72 @@ namespace unordered
#endif
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_NOEXCEPT
{
return table_.node_alloc();
}
// size and capacity
bool empty() const
bool empty() const BOOST_NOEXCEPT
{
return table_.size_ == 0;
}
size_type size() const
size_type size() const BOOST_NOEXCEPT
{
return table_.size_;
}
size_type max_size() const;
size_type max_size() const BOOST_NOEXCEPT;
// iterators
iterator begin()
iterator begin() BOOST_NOEXCEPT
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const
const_iterator begin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end()
iterator end() BOOST_NOEXCEPT
{
return iterator();
}
const_iterator end() const
const_iterator end() const BOOST_NOEXCEPT
{
return const_iterator();
}
const_iterator cbegin() const
const_iterator cbegin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const
const_iterator cend() const BOOST_NOEXCEPT
{
return const_iterator();
}
// emplace
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
iterator emplace(Args&&... args)
iterator emplace(BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
}
@@ -886,7 +886,7 @@ namespace unordered
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
@@ -932,12 +932,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const
size_type bucket_count() const BOOST_NOEXCEPT
{
return table_.bucket_count_;
}
size_type max_bucket_count() const
size_type max_bucket_count() const BOOST_NOEXCEPT
{
return table_.max_bucket_count();
}
@@ -946,21 +946,19 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table_.hash_function()(k) % table_.bucket_count_;
return table_.hash_to_bucket(table_.hash(k));
}
local_iterator begin(size_type n)
{
return table_.size_ ? local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
local_iterator();
return local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator begin(size_type n) const
{
return table_.size_ ? const_local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
const_local_iterator();
return const_local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
local_iterator end(size_type)
@@ -975,9 +973,8 @@ namespace unordered
const_local_iterator cbegin(size_type n) const
{
return table_.size_ ? const_local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
const_local_iterator();
return const_local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator cend(size_type) const
@@ -987,14 +984,15 @@ namespace unordered
// hash policy
float max_load_factor() const
float max_load_factor() const BOOST_NOEXCEPT
{
return table_.mlf_;
}
float load_factor() const;
void max_load_factor(float);
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<K,T,H,P,A>(
@@ -1064,7 +1062,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::~unordered_map() {}
unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
@@ -1073,7 +1071,7 @@ namespace unordered
{
}
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
@@ -1084,7 +1082,7 @@ namespace unordered
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
@@ -1112,7 +1110,7 @@ namespace unordered
// size and capacity
template <class K, class T, class H, class P, class A>
std::size_t unordered_map<K,T,H,P,A>::max_size() const
std::size_t unordered_map<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
{
return table_.max_size();
}
@@ -1126,7 +1124,7 @@ namespace unordered
table_.insert_range(first, last);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
void unordered_map<K,T,H,P,A>::insert(
std::initializer_list<value_type> list)
@@ -1139,7 +1137,7 @@ namespace unordered
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
return table_.erase(position);
}
template <class K, class T, class H, class P, class A>
@@ -1154,7 +1152,7 @@ namespace unordered
unordered_map<K,T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
return table_.erase_range(first, last);
}
template <class K, class T, class H, class P, class A>
@@ -1212,14 +1210,14 @@ namespace unordered
typename unordered_map<K,T,H,P,A>::iterator
unordered_map<K,T,H,P,A>::find(const key_type& k)
{
return iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K,T,H,P,A>::const_iterator
unordered_map<K,T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
@@ -1231,7 +1229,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1243,7 +1241,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1281,13 +1279,13 @@ namespace unordered
// hash policy
template <class K, class T, class H, class P, class A>
float unordered_map<K,T,H,P,A>::load_factor() const
float unordered_map<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
{
return table_.load_factor();
}
template <class K, class T, class H, class P, class A>
void unordered_map<K,T,H,P,A>::max_load_factor(float m)
void unordered_map<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
{
table_.max_load_factor(m);
}
@@ -1298,6 +1296,12 @@ namespace unordered
table_.rehash(n);
}
template <class K, class T, class H, class P, class A>
void unordered_map<K,T,H,P,A>::reserve(size_type n)
{
table_.reserve(n);
}
template <class K, class T, class H, class P, class A>
inline bool operator==(
unordered_map<K,T,H,P,A> const& m1,
@@ -1391,7 +1395,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::~unordered_multimap() {}
unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
@@ -1400,7 +1404,7 @@ namespace unordered
{
}
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
@@ -1411,7 +1415,7 @@ namespace unordered
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
@@ -1439,7 +1443,7 @@ namespace unordered
// size and capacity
template <class K, class T, class H, class P, class A>
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
{
return table_.max_size();
}
@@ -1453,7 +1457,7 @@ namespace unordered
table_.insert_range(first, last);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class K, class T, class H, class P, class A>
void unordered_multimap<K,T,H,P,A>::insert(
std::initializer_list<value_type> list)
@@ -1466,7 +1470,7 @@ namespace unordered
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
return table_.erase(position);
}
template <class K, class T, class H, class P, class A>
@@ -1481,7 +1485,7 @@ namespace unordered
unordered_multimap<K,T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
return table_.erase_range(first, last);
}
template <class K, class T, class H, class P, class A>
@@ -1518,14 +1522,14 @@ namespace unordered
typename unordered_multimap<K,T,H,P,A>::iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k)
{
return iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
typename unordered_multimap<K,T,H,P,A>::const_iterator
unordered_multimap<K,T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class K, class T, class H, class P, class A>
@@ -1537,7 +1541,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
return iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1549,7 +1553,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class K, class T, class H, class P, class A>
@@ -1587,13 +1591,13 @@ namespace unordered
// hash policy
template <class K, class T, class H, class P, class A>
float unordered_multimap<K,T,H,P,A>::load_factor() const
float unordered_multimap<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
{
return table_.load_factor();
}
template <class K, class T, class H, class P, class A>
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m)
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
{
table_.max_load_factor(m);
}
@@ -1604,6 +1608,12 @@ namespace unordered
table_.rehash(n);
}
template <class K, class T, class H, class P, class A>
void unordered_multimap<K,T,H,P,A>::reserve(size_type n)
{
table_.reserve(n);
}
template <class K, class T, class H, class P, class A>
inline bool operator==(
unordered_multimap<K,T,H,P,A> const& m1,
+20 -2
View File
@@ -6,16 +6,27 @@
#ifndef BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
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;
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&);
@@ -26,6 +37,13 @@ namespace boost
inline void swap(unordered_map<K, T, H, P, A>&,
unordered_map<K, T, H, P, A>&);
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&);
+111 -101
View File
@@ -9,19 +9,19 @@
#ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/unordered_set_fwd.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/equivalent.hpp>
#include <boost/unordered/detail/unique.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
#include <initializer_list>
#endif
@@ -55,7 +55,6 @@ namespace unordered
private:
typedef boost::unordered::detail::set<A, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
@@ -117,21 +116,23 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set(BOOST_RV_REF(unordered_set) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set(
std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
@@ -142,7 +143,7 @@ namespace unordered
// Destructor
~unordered_set();
~unordered_set() BOOST_NOEXCEPT;
// Assign
@@ -165,7 +166,7 @@ namespace unordered
return *this;
}
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set& operator=(unordered_set&& x)
{
table_.move_assign(x.table_);
@@ -174,72 +175,72 @@ namespace unordered
#endif
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_set& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_NOEXCEPT
{
return table_.node_alloc();
}
// size and capacity
bool empty() const
bool empty() const BOOST_NOEXCEPT
{
return table_.size_ == 0;
}
size_type size() const
size_type size() const BOOST_NOEXCEPT
{
return table_.size_;
}
size_type max_size() const;
size_type max_size() const BOOST_NOEXCEPT;
// iterators
iterator begin()
iterator begin() BOOST_NOEXCEPT
{
return iterator(table_.begin());
return table_.begin();
}
const_iterator begin() const
const_iterator begin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
return table_.begin();
}
iterator end()
iterator end() BOOST_NOEXCEPT
{
return iterator();
}
const_iterator end() const
const_iterator end() const BOOST_NOEXCEPT
{
return const_iterator();
}
const_iterator cbegin() const
const_iterator cbegin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
return table_.begin();
}
const_iterator cend() const
const_iterator cend() const BOOST_NOEXCEPT
{
return const_iterator();
}
// emplace
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args)
std::pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...).first;
}
@@ -400,7 +401,7 @@ namespace unordered
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
@@ -436,12 +437,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const
size_type bucket_count() const BOOST_NOEXCEPT
{
return table_.bucket_count_;
}
size_type max_bucket_count() const
size_type max_bucket_count() const BOOST_NOEXCEPT
{
return table_.max_bucket_count();
}
@@ -450,21 +451,19 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table_.hash_function()(k) % table_.bucket_count_;
return table_.hash_to_bucket(table_.hash(k));
}
local_iterator begin(size_type n)
{
return table_.size_ ? local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
local_iterator();
return local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator begin(size_type n) const
{
return table_.size_ ? const_local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
const_local_iterator();
return const_local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
local_iterator end(size_type)
@@ -479,9 +478,8 @@ namespace unordered
const_local_iterator cbegin(size_type n) const
{
return table_.size_ ? const_local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
const_local_iterator();
return const_local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator cend(size_type) const
@@ -491,14 +489,15 @@ namespace unordered
// hash policy
float max_load_factor() const
float max_load_factor() const BOOST_NOEXCEPT
{
return table_.mlf_;
}
float load_factor() const;
void max_load_factor(float);
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<T,H,P,A>(
@@ -525,7 +524,6 @@ namespace unordered
private:
typedef boost::unordered::detail::multiset<A, T, H, P> types;
typedef typename types::allocator value_allocator;
typedef typename types::traits allocator_traits;
typedef typename types::table table;
@@ -587,21 +585,23 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_RVALUE_REFERENCES)
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#endif
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&&, allocator_type const&);
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset(
std::initializer_list<value_type>,
size_type = boost::unordered::detail::default_bucket_count,
@@ -612,7 +612,7 @@ namespace unordered
// Destructor
~unordered_multiset();
~unordered_multiset() BOOST_NOEXCEPT;
// Assign
@@ -636,7 +636,7 @@ namespace unordered
return *this;
}
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset& operator=(unordered_multiset&& x)
{
table_.move_assign(x.table_);
@@ -645,72 +645,72 @@ namespace unordered
#endif
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multiset& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const
allocator_type get_allocator() const BOOST_NOEXCEPT
{
return table_.node_alloc();
}
// size and capacity
bool empty() const
bool empty() const BOOST_NOEXCEPT
{
return table_.size_ == 0;
}
size_type size() const
size_type size() const BOOST_NOEXCEPT
{
return table_.size_;
}
size_type max_size() const;
size_type max_size() const BOOST_NOEXCEPT;
// iterators
iterator begin()
iterator begin() BOOST_NOEXCEPT
{
return iterator(table_.begin());
}
const_iterator begin() const
const_iterator begin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
}
iterator end()
iterator end() BOOST_NOEXCEPT
{
return iterator();
}
const_iterator end() const
const_iterator end() const BOOST_NOEXCEPT
{
return const_iterator();
}
const_iterator cbegin() const
const_iterator cbegin() const BOOST_NOEXCEPT
{
return const_iterator(table_.begin());
}
const_iterator cend() const
const_iterator cend() const BOOST_NOEXCEPT
{
return const_iterator();
}
// emplace
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
iterator emplace(Args&&... args)
iterator emplace(BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
}
template <class... Args>
iterator emplace_hint(const_iterator, Args&&... args)
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
}
@@ -871,7 +871,7 @@ namespace unordered
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
void insert(std::initializer_list<value_type>);
#endif
@@ -907,12 +907,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const
size_type bucket_count() const BOOST_NOEXCEPT
{
return table_.bucket_count_;
}
size_type max_bucket_count() const
size_type max_bucket_count() const BOOST_NOEXCEPT
{
return table_.max_bucket_count();
}
@@ -921,21 +921,19 @@ namespace unordered
size_type bucket(const key_type& k) const
{
return table_.hash_function()(k) % table_.bucket_count_;
return table_.hash_to_bucket(table_.hash(k));
}
local_iterator begin(size_type n)
{
return table_.size_ ? local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
local_iterator();
return local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator begin(size_type n) const
{
return table_.size_ ? const_local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
const_local_iterator();
return const_local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
local_iterator end(size_type)
@@ -950,9 +948,8 @@ namespace unordered
const_local_iterator cbegin(size_type n) const
{
return table_.size_ ? const_local_iterator(
table_.get_start(n), n, table_.bucket_count_) :
const_local_iterator();
return const_local_iterator(
table_.begin(n), n, table_.bucket_count_);
}
const_local_iterator cend(size_type) const
@@ -962,14 +959,15 @@ namespace unordered
// hash policy
float max_load_factor() const
float max_load_factor() const BOOST_NOEXCEPT
{
return table_.mlf_;
}
float load_factor() const;
void max_load_factor(float);
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
void rehash(size_type);
void reserve(size_type);
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x0582)
friend bool operator==<T,H,P,A>(
@@ -1039,7 +1037,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::~unordered_set() {}
unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
@@ -1048,7 +1046,7 @@ namespace unordered
{
}
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
@@ -1059,7 +1057,7 @@ namespace unordered
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
@@ -1087,7 +1085,7 @@ namespace unordered
// size and capacity
template <class T, class H, class P, class A>
std::size_t unordered_set<T,H,P,A>::max_size() const
std::size_t unordered_set<T,H,P,A>::max_size() const BOOST_NOEXCEPT
{
return table_.max_size();
}
@@ -1101,7 +1099,7 @@ namespace unordered
table_.insert_range(first, last);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
void unordered_set<T,H,P,A>::insert(
std::initializer_list<value_type> list)
@@ -1114,7 +1112,7 @@ namespace unordered
typename unordered_set<T,H,P,A>::iterator
unordered_set<T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
return table_.erase(position);
}
template <class T, class H, class P, class A>
@@ -1129,7 +1127,7 @@ namespace unordered
unordered_set<T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
return table_.erase_range(first, last);
}
template <class T, class H, class P, class A>
@@ -1166,7 +1164,7 @@ namespace unordered
typename unordered_set<T,H,P,A>::const_iterator
unordered_set<T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class T, class H, class P, class A>
@@ -1178,7 +1176,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class T, class H, class P, class A>
@@ -1207,13 +1205,13 @@ namespace unordered
// hash policy
template <class T, class H, class P, class A>
float unordered_set<T,H,P,A>::load_factor() const
float unordered_set<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
{
return table_.load_factor();
}
template <class T, class H, class P, class A>
void unordered_set<T,H,P,A>::max_load_factor(float m)
void unordered_set<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
{
table_.max_load_factor(m);
}
@@ -1224,6 +1222,12 @@ namespace unordered
table_.rehash(n);
}
template <class T, class H, class P, class A>
void unordered_set<T,H,P,A>::reserve(size_type n)
{
table_.reserve(n);
}
template <class T, class H, class P, class A>
inline bool operator==(
unordered_set<T,H,P,A> const& m1,
@@ -1317,7 +1321,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::~unordered_multiset() {}
unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
@@ -1326,7 +1330,7 @@ namespace unordered
{
}
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
@@ -1337,7 +1341,7 @@ namespace unordered
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
@@ -1365,7 +1369,7 @@ namespace unordered
// size and capacity
template <class T, class H, class P, class A>
std::size_t unordered_multiset<T,H,P,A>::max_size() const
std::size_t unordered_multiset<T,H,P,A>::max_size() const BOOST_NOEXCEPT
{
return table_.max_size();
}
@@ -1379,7 +1383,7 @@ namespace unordered
table_.insert_range(first, last);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template <class T, class H, class P, class A>
void unordered_multiset<T,H,P,A>::insert(
std::initializer_list<value_type> list)
@@ -1392,7 +1396,7 @@ namespace unordered
typename unordered_multiset<T,H,P,A>::iterator
unordered_multiset<T,H,P,A>::erase(const_iterator position)
{
return iterator(table_.erase(position.node_));
return table_.erase(position);
}
template <class T, class H, class P, class A>
@@ -1407,7 +1411,7 @@ namespace unordered
unordered_multiset<T,H,P,A>::erase(
const_iterator first, const_iterator last)
{
return iterator(table_.erase_range(first.node_, last.node_));
return table_.erase_range(first, last);
}
template <class T, class H, class P, class A>
@@ -1444,7 +1448,7 @@ namespace unordered
typename unordered_multiset<T,H,P,A>::const_iterator
unordered_multiset<T,H,P,A>::find(const key_type& k) const
{
return const_iterator(table_.find_node(k));
return table_.find_node(k);
}
template <class T, class H, class P, class A>
@@ -1456,7 +1460,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
return const_iterator(table_.generic_find_node(k, hash, eq));
return table_.generic_find_node(k, hash, eq);
}
template <class T, class H, class P, class A>
@@ -1485,13 +1489,13 @@ namespace unordered
// hash policy
template <class T, class H, class P, class A>
float unordered_multiset<T,H,P,A>::load_factor() const
float unordered_multiset<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
{
return table_.load_factor();
}
template <class T, class H, class P, class A>
void unordered_multiset<T,H,P,A>::max_load_factor(float m)
void unordered_multiset<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
{
table_.max_load_factor(m);
}
@@ -1502,6 +1506,12 @@ namespace unordered
table_.rehash(n);
}
template <class T, class H, class P, class A>
void unordered_multiset<T,H,P,A>::reserve(size_type n)
{
table_.reserve(n);
}
template <class T, class H, class P, class A>
inline bool operator==(
unordered_multiset<T,H,P,A> const& m1,
+18 -2
View File
@@ -6,16 +6,26 @@
#ifndef BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
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;
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&);
@@ -26,6 +36,12 @@ namespace boost
inline void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &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, class P, class A>
inline bool operator==(unordered_multiset<T, H, P, A> const&,
unordered_multiset<T, H, P, A> const&);
+3 -2
View File
@@ -9,8 +9,9 @@
#ifndef BOOST_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/unordered_map.hpp>
+3 -2
View File
@@ -9,8 +9,9 @@
#ifndef BOOST_UNORDERED_SET_HPP_INCLUDED
#define BOOST_UNORDERED_SET_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/unordered_set.hpp>
+17
View File
@@ -0,0 +1,17 @@
{
"key": "unordered",
"name": "Unordered",
"authors": [
"Daniel James"
],
"maintainers": [
"Daniel James <dnljms -at- gmail.com>"
],
"description": "Unordered associative containers.",
"std": [
"tr1"
],
"category": [
"Containers"
]
}
+2 -7
View File
@@ -12,13 +12,8 @@ project unordered-test/exception-tests
: requirements
<warnings>all
<toolset>intel:<warnings>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
#<toolset>gcc:<define>_GLIBCXX_DEBUG
#<toolset>darwin:<define>_GLIBCXX_DEBUG
#<toolset>msvc:<warnings-as-errors>on
#<toolset>gcc:<warnings-as-errors>on
#<toolset>darwin:<warnings-as-errors>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
;
test-suite unordered-exception
+28 -9
View File
@@ -3,8 +3,6 @@
// 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/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -13,7 +11,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t seed(12847);
test::seed_t initialize_seed(12847);
template <class T>
struct self_assign_base : public test::exception_base
@@ -41,26 +39,40 @@ template <class T>
struct assign_base : public test::exception_base
{
const test::random_values<T> x_values, y_values;
const T x,y;
T x,y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2) :
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2,
float mlf1 = 1.0, float mlf2 = 1.0) :
x_values(count1),
y_values(count2),
x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1),
allocator_type(tag1)),
y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2),
allocator_type(tag2))
{}
{
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); }
{
test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it.
T& y = const_cast<T&>(x1);
if (x_values.size()) {
y.emplace(*x_values.begin());
test::check_equivalent_keys(y);
}
}
};
template <class T>
@@ -87,7 +99,14 @@ struct assign_test4 : assign_base<T>
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
};
RUN_EXCEPTION_TESTS(
template <class T>
struct assign_test5 : assign_base<T>
{
assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
};
EXCEPTION_TESTS(
(self_assign_test1)(self_assign_test2)
(assign_test1)(assign_test2)(assign_test3)(assign_test4),
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
CONTAINER_SEQ)
RUN_TESTS()
@@ -3,15 +3,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)
#include "../helpers/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/input_iterator.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t seed(91274);
test::seed_t initialize_seed(91274);
struct objects
{
@@ -161,7 +159,7 @@ struct copy_range_construct_test : public range<T>, objects
}
};
RUN_EXCEPTION_TESTS(
EXCEPTION_TESTS(
(construct_test1)
(construct_test2)
(construct_test3)
@@ -176,3 +174,4 @@ RUN_EXCEPTION_TESTS(
(input_range_construct_test)
(copy_range_construct_test),
CONTAINER_SEQ)
RUN_TESTS()
+4 -2
View File
@@ -3,8 +3,10 @@
// 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/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include "../objects/exception.hpp"
typedef boost::unordered_set<
@@ -16,13 +18,13 @@ typedef boost::unordered_multiset<
test::exception::object,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> > test_multiset;
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::allocator<test::exception::object> > test_map;
test::exception::allocator2<test::exception::object> > test_map;
typedef boost::unordered_multimap<
test::exception::object,
test::exception::object,
+3 -4
View File
@@ -3,14 +3,12 @@
// 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/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t seed(73041);
test::seed_t initialize_seed(73041);
template <class T>
struct copy_test1 : public test::exception_base
@@ -66,6 +64,7 @@ struct copy_with_allocator_test : public test::exception_base
}
};
RUN_EXCEPTION_TESTS(
EXCEPTION_TESTS(
(copy_test1)(copy_test2)(copy_test3)(copy_with_allocator_test),
CONTAINER_SEQ)
RUN_TESTS()
+3 -4
View File
@@ -3,14 +3,12 @@
// 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/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/helpers.hpp"
test::seed_t seed(835193);
test::seed_t initialize_seed(835193);
template <class T>
struct erase_test_base : public test::exception_base
@@ -51,6 +49,7 @@ struct erase_by_key_test1 : public erase_test_base<T>
}
};
RUN_EXCEPTION_TESTS(
EXCEPTION_TESTS(
(erase_by_key_test1),
CONTAINER_SEQ)
RUN_TESTS()
+12 -13
View File
@@ -3,8 +3,6 @@
// 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/prefix.hpp"
#include "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -13,7 +11,7 @@
#include <boost/utility.hpp>
#include <cmath>
test::seed_t seed(747373);
test::seed_t initialize_seed(747373);
template <class T>
struct insert_test_base : public test::exception_base
@@ -34,12 +32,12 @@ struct insert_test_base : public test::exception_base
std::string scope(test::scope);
if(scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::exception::detail::tracker.count_allocations);
strong.test(x, test::detail::tracker.count_allocations);
test::check_equivalent_keys(x);
}
};
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class T>
struct emplace_test1 : public insert_test_base<T>
@@ -51,7 +49,7 @@ struct emplace_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.emplace(*it);
}
}
@@ -69,7 +67,7 @@ struct insert_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it);
}
}
@@ -85,7 +83,7 @@ struct insert_test2 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(x.begin(), *it);
}
}
@@ -113,7 +111,7 @@ struct insert_test4 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(it, boost::next(it));
}
}
@@ -152,7 +150,7 @@ struct insert_test_rehash1 : public insert_test_base<T>
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
pos = x.insert(pos, *it);
}
@@ -176,7 +174,7 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x, test::exception::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it);
}
@@ -238,11 +236,12 @@ struct insert_test_rehash3 : public insert_test_base<T>
(insert_test1)(insert_test2)(insert_test3)(insert_test4) \
(insert_test_rehash1)(insert_test_rehash2)(insert_test_rehash3)
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
#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
RUN_EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
RUN_TESTS()
+3 -5
View File
@@ -3,8 +3,6 @@
// 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/prefix.hpp"
#include "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -13,7 +11,7 @@
#include <iostream>
test::seed_t seed(3298597);
test::seed_t initialize_seed(3298597);
template <class T>
struct rehash_test_base : public test::exception_base
@@ -81,7 +79,7 @@ struct rehash_test4 : rehash_test_base<T>
void run(T& x) const { x.rehash(0); }
};
RUN_EXCEPTION_TESTS(
EXCEPTION_TESTS(
(rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(rehash_test4),
CONTAINER_SEQ)
RUN_TESTS()
+7 -5
View File
@@ -3,8 +3,6 @@
// 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/prefix.hpp"
#include "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -13,7 +11,7 @@
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t seed(9387);
test::seed_t initialize_seed(9387);
template <class T>
struct self_swap_base : public test::exception_base
@@ -62,7 +60,9 @@ struct swap_base : public test::exception_base
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(tag2))
key_equal(tag2), allocator_type(
T::allocator_type::propagate_on_container_swap::value ?
tag2 : tag1))
{}
struct data_type {
@@ -73,6 +73,7 @@ struct swap_base : public test::exception_base
};
data_type init() const { return data_type(initial_x, initial_y); }
void run(data_type& d) const {
try {
d.x.swap(d.y);
@@ -117,7 +118,8 @@ struct swap_test4 : swap_base<T>
swap_test4() : swap_base<T>(10, 10, 1, 2) {}
};
RUN_EXCEPTION_TESTS(
EXCEPTION_TESTS(
(self_swap_test1)(self_swap_test2)
(swap_test1)(swap_test2)(swap_test3)(swap_test4),
CONTAINER_SEQ)
RUN_TESTS()
-84
View File
@@ -1,84 +0,0 @@
// 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)
#if !defined(BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER)
#define BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER
#include <cstddef>
#include <cstdlib>
#include <boost/limits.hpp>
#include <new>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
namespace test
{
template <class T>
struct malloc_allocator
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef malloc_allocator<U> other; };
malloc_allocator() {}
template <class Y> malloc_allocator(malloc_allocator<Y> const&) {}
malloc_allocator(malloc_allocator const&) {}
pointer address(reference r) { return &r; }
const_pointer address(const_reference r) { return &r; }
pointer allocate(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(T)));
if(!ptr) throw std::bad_alloc();
return ptr;
}
pointer allocate(size_type n, void const* u) { return allocate(n); }
void deallocate(pointer p, size_type) {
using namespace std;
free(p);
}
void construct(pointer p, T const& t) { new(p) T(t); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const {
return (std::numeric_limits<size_type>::max)();
}
bool operator==(malloc_allocator const&) const { return true; }
bool operator!=(malloc_allocator const&) const { return false; }
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T> void deallocate(T* p, size_type) {
using namespace std;
free(p);
}
char* _Charalloc(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(char)));
if(!ptr) throw std::bad_alloc();
return (char*) ptr;
}
#endif
};
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#endif
+4 -4
View File
@@ -6,7 +6,7 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER
#include <boost/mpl/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
@@ -18,19 +18,19 @@ namespace test
template <class T2>
static void equals(T2)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void equals_ref(T2&)
{
BOOST_MPL_ASSERT((boost::is_same<T1, T2>));
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
}
template <class T2>
static void convertible(T2)
{
BOOST_MPL_ASSERT((boost::is_convertible<T2, T1>));
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
}
};
}
+8 -16
View File
@@ -52,30 +52,22 @@ namespace test {
}
};
template <class T>
struct counted_object
{
static object_count count_;
counted_object() { count_.construct(); }
counted_object(counted_object const&) { count_.construct(); }
~counted_object() { count_.destruct(); }
};
template <class T> object_count counted_object<T>::count_;
struct globally_counted_object
: counted_object<globally_counted_object> {};
// 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 = globally_counted_object::count_;
object_count global_object_count;
}
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 {
int instances;
+23 -8
View File
@@ -20,22 +20,37 @@
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>)); \
} \
} \
# define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
#define RUN_EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, \
(test_seq)(param_seq)) \
RUN_TESTS() \
#define EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, \
(test_seq)((1))(param_seq))
#define RUN_EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE( \
#define EXCEPTION_TESTS_REPEAT(n, test_seq, 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(1, 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(1, product), \
BOOST_PP_SEQ_ELEM(2, product) \
) \
#define UNORDERED_SCOPE(scope_name) \
+26 -6
View File
@@ -13,7 +13,6 @@
#include <cmath>
#include "./metafunctions.hpp"
#include "./helpers.hpp"
#include "./allocator.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -29,10 +28,7 @@ namespace test
{
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
// Boost.Test was reporting memory leaks for std::set on g++-3.3.
// So I work around it by using malloc.
std::set<key_type, std::less<key_type>,
test::malloc_allocator<key_type> > found_;
std::set<key_type, std::less<key_type> > found_;
BOOST_DEDUCED_TYPENAME X::const_iterator
it = x1.begin(), end = x1.end();
@@ -86,16 +82,40 @@ namespace test
}
};
// Finally, check that size matches up.
// 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;
}
// Check the load factor.
float load_factor =
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.");
// Check that size in the buckets matches up.
BOOST_DEDUCED_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;
}
}
if(x1.size() != bucket_size) {
BOOST_ERROR("x1.size() doesn't match bucket size.");
std::cout<<x1.size()<<"/"<<bucket_size<<std::endl;
}
}
}
+3 -3
View File
@@ -219,14 +219,14 @@ namespace test
data_.last_ptr_ = &data_.first_;
}
void erase(const_iterator start, const_iterator end) {
void erase(const_iterator i, const_iterator j) {
node** ptr = &data_.first_;
while(*ptr != start.ptr_) {
while(*ptr != i.ptr_) {
ptr = &(*ptr)->next_;
}
while(*ptr != end.ptr_) {
while(*ptr != j.ptr_) {
node* to_delete = *ptr;
*ptr = (*ptr)->next_;
--data_.size_;
+6 -52
View File
@@ -8,10 +8,8 @@
#include <memory>
#include <map>
#include <boost/mpl/apply.hpp>
#include <boost/assert.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include "../helpers/test.hpp"
namespace test
@@ -53,30 +51,10 @@ namespace test
}
};
template <class Alloc>
struct allocator_memory_type_gen {
typedef std::map<memory_area, memory_track, memory_area_compare,
Alloc> type;
};
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
template <>
struct allocator_memory_type_gen<int> {
typedef std::map<memory_area, memory_track, memory_area_compare>
type;
};
#endif
template <class Alloc = std::allocator<int> >
struct memory_tracker {
typedef BOOST_DEDUCED_TYPENAME
::boost::unordered::detail::rebind_wrap<Alloc,
std::pair<memory_area const, memory_track> >::type
allocator_type;
typedef BOOST_DEDUCED_TYPENAME
allocator_memory_type_gen<allocator_type>::type
allocated_memory_type;
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;
@@ -139,7 +117,7 @@ namespace test
void track_deallocate(void* ptr, std::size_t n, std::size_t size,
int tag, bool check_tag_ = true)
{
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos =
allocated_memory_type::iterator pos =
allocated_memory.find(
memory_area(ptr, (char*) ptr + n * size));
if(pos == allocated_memory.end()) {
@@ -177,33 +155,9 @@ namespace test
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker<std::allocator<int> > tracker;
test::detail::memory_tracker tracker;
}
}
template <int Value>
struct bool_type {
enum { value = (Value ? true : false) };
};
struct true_type {
enum { value = true };
};
struct false_type {
enum { value = false };
};
struct convert_from_anything
{
template <typename T>
convert_from_anything(T const&) {}
};
int selected_count(convert_from_anything)
{
return 0;
}
}
#endif
+10 -49
View File
@@ -8,72 +8,33 @@
#include <boost/config.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/not.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
namespace test
{
/*
struct unordered_set_type { char x[100]; };
struct unordered_multiset_type { char x[200]; };
struct unordered_map_type { char x[300]; };
struct unordered_multimap_type { char x[400]; };
template <class V, class H, class P, class A>
unordered_set_type container_type(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
unordered_multiset_type container_type(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_map_type container_type(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
unordered_multimap_type container_type(
boost::unordered_multimap<K, M, H, P, A> const*);
*/
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_map
: public boost::mpl::not_<is_set<Container> > {};
struct yes_type { char x[100]; };
struct no_type { char x[200]; };
template <class V, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_set<V, H, P, A> const*);
template <class V, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multiset<V, H, P, A> const*);
template <class K, class M, class H, class P, class A>
yes_type has_unique_key_impl(
boost::unordered_map<K, M, H, P, A> const*);
template <class K, class M, class H, class P, class A>
no_type has_unique_key_impl(
boost::unordered_multimap<K, M, H, P, A> const*);
template <class Container>
struct has_unique_keys
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(yes_type));
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class Container>
struct has_equivalent_keys
template <class V, class H, class P, class A>
struct has_unique_keys<boost::unordered_set<V, H, P, A> >
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(no_type));
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class K, class M, class H, class P, class A>
struct has_unique_keys<boost::unordered_map<K, M, H, P, A> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
+10
View File
@@ -0,0 +1,10 @@
// Copyright 2012 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 this after the boost headers, but before other test headers.
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
+20 -18
View File
@@ -8,7 +8,7 @@
#include "./list.hpp"
#include <algorithm>
#include <boost/mpl/if.hpp>
#include <boost/detail/select_type.hpp>
#include "./generators.hpp"
#include "./metafunctions.hpp"
@@ -33,14 +33,15 @@ namespace test
void fill(T& x, std::size_t len) {
value_type* value_ptr = 0;
int* int_ptr = 0;
len += x.size();
for(std::size_t i = 0; i < len; ++i) {
for (std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr);
for(int count =
type_ == generate_collisions ?
generate(int_ptr) % 10 : 1;
count; --count) {
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(int j = 0; j < count; ++j) {
x.push_back(value);
}
}
@@ -64,16 +65,15 @@ namespace test
mapped_type* mapped_ptr = 0;
int* int_ptr = 0;
for(std::size_t i = 0; i < len; ++i) {
for (std::size_t i = 0; i < len; ++i) {
key_type key = generate(key_ptr);
for(int count =
type_ == generate_collisions ?
generate(int_ptr) % 10 : 1;
count; --count) {
x.push_back(
std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr)));
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(int j = 0; j < count; ++j) {
x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr)));
}
}
}
@@ -81,10 +81,12 @@ namespace test
template <class X>
struct unordered_generator_base
: public boost::mpl::if_<
test::is_set<X>,
: public boost::detail::if_true<
test::is_set<X>::value
>::BOOST_NESTED_TEMPLATE then<
test::unordered_generator_set<X>,
test::unordered_generator_map<X> >
test::unordered_generator_map<X>
>
{
};
@@ -104,7 +106,7 @@ namespace test
random_values(int count, test::random_generator const& generator =
test::default_generator)
{
static test::unordered_generator<X> gen(generator);
test::unordered_generator<X> gen(generator);
gen.fill(*this, count);
}
};
-1
View File
@@ -8,7 +8,6 @@
#include <boost/config.hpp>
#include <iterator>
#include "./metafunctions.hpp"
#include "./equivalent.hpp"
#include "./list.hpp"
#include "./exception_test.hpp"
+13 -5
View File
@@ -76,21 +76,29 @@ namespace test {
// 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)) 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) \
#define UNORDERED_TEST_OP(r, product) \
UNORDERED_TEST_OP2( \
BOOST_PP_SEQ_HEAD(product), \
BOOST_PP_SEQ_TAIL(product)) \
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, params) \
#define UNORDERED_TEST_OP2(name, n, params) \
UNORDERED_AUTO_TEST( \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) \
{ \
name BOOST_PP_SEQ_TO_TUPLE(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)) \
#endif
+45 -63
View File
@@ -13,9 +13,6 @@
#include <map>
#include <iterator>
#include <algorithm>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_same.hpp>
#include "../objects/fwd.hpp"
#include "./metafunctions.hpp"
@@ -25,21 +22,17 @@
namespace test
{
template <class X>
struct equals_to_compare2
: public boost::mpl::identity<
std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> >
template <typename X>
struct equals_to_compare
{
typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type>
type;
};
template <class X>
struct equals_to_compare
: public boost::mpl::eval_if<
boost::is_same<X, test::equal_to>,
boost::mpl::identity<test::less>,
equals_to_compare2<X>
>
template <>
struct equals_to_compare<test::equal_to>
{
typedef test::less type;
};
template <class X1, class X2>
@@ -67,51 +60,40 @@ namespace test
values2.begin(), test::equivalent));
}
template <class X>
struct ordered_set : public
boost::mpl::if_<
test::has_unique_keys<X>,
std::set<
BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>,
std::multiset<
BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME equals_to_compare<
BOOST_DEDUCED_TYPENAME X::key_equal
>::type
>
> {};
template <typename X>
struct ordered_base;
template <class X>
struct ordered_map : public
boost::mpl::if_<
test::has_unique_keys<X>,
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
>,
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
>
> {};
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_set<V, H, P, A> >
{
typedef std::set<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class X>
struct ordered_base : public
boost::mpl::eval_if<
test::is_set<X>,
test::ordered_set<X>,
test::ordered_map<X>
> {};
template <class V, class H, class P, class A>
struct ordered_base<boost::unordered_multiset<V, H, P, A> >
{
typedef std::multiset<V,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_map<K, M, H, P, A> >
{
typedef std::map<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class K, class M, class H, class P, class A>
struct ordered_base<boost::unordered_multimap<K, M, H, P, A> >
{
typedef std::multimap<K, M,
BOOST_DEDUCED_TYPENAME equals_to_compare<P>::type>
type;
};
template <class X>
class ordered : public ordered_base<X>::type
@@ -124,8 +106,8 @@ namespace test
: base()
{}
explicit ordered(key_compare const& compare)
: base(compare)
explicit ordered(key_compare const& kc)
: base(kc)
{}
void compare(X const& x)
@@ -143,10 +125,10 @@ namespace test
}
template <class It>
void insert_range(It begin, It end) {
while(begin != end) {
this->insert(*begin);
++begin;
void insert_range(It b, It e) {
while(b != e) {
this->insert(*b);
++b;
}
}
};
+20 -4
View File
@@ -21,7 +21,8 @@ namespace test
is_select_on_copy = 0,
is_propagate_on_swap = 0,
is_propagate_on_assign = 0,
is_propagate_on_move = 0
is_propagate_on_move = 0,
cxx11_construct = 0
};
};
@@ -31,7 +32,8 @@ namespace test
is_select_on_copy = 1,
is_propagate_on_swap = 1,
is_propagate_on_assign = 1,
is_propagate_on_move = 1
is_propagate_on_move = 1,
cxx11_construct = 1
};
};
@@ -168,8 +170,8 @@ namespace test
new(p) T(t);
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
template<typename... Args> void construct(T* p, Args&&... args) {
#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)...);
}
@@ -291,6 +293,20 @@ namespace test
return x.tag_ == y.tag_;
}
// Function to check how many times an allocator has been selected,
// return 0 for other allocators.
struct convert_from_anything
{
template <typename T>
convert_from_anything(T const&) {}
};
inline int selected_count(convert_from_anything)
{
return 0;
}
template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x)
{
+193 -22
View File
@@ -13,21 +13,12 @@
#include <boost/limits.hpp>
#include <new>
#include "../helpers/fwd.hpp"
#include "../helpers/allocator.hpp"
#include "../helpers/memory.hpp"
namespace test
{
namespace exception
{
namespace detail
{
namespace
{
test::detail::memory_tracker<test::malloc_allocator<int> > tracker;
}
}
class object;
class hash;
class equal_to;
@@ -259,7 +250,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator default constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_)
@@ -267,7 +258,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator template copy constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
allocator(allocator const& x) : tag_(x.tag_)
@@ -275,11 +266,11 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator copy constructor.");
}
detail::tracker.allocator_ref();
test::detail::tracker.allocator_ref();
}
~allocator() {
detail::tracker.allocator_unref();
test::detail::tracker.allocator_unref();
}
allocator& operator=(allocator const& x) {
@@ -317,7 +308,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -333,7 +324,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -343,7 +334,7 @@ namespace exception
{
//::operator delete((void*) p);
if(p) {
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
using namespace std;
free(p);
}
@@ -354,21 +345,21 @@ namespace exception
UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(t);
}
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
UNORDERED_SCOPE(allocator::construct(pointer, BOOST_FWD_REF(Args)...)) {
UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(boost::forward<Args>(args)...);
}
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#endif
void destroy(T* p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
@@ -410,6 +401,186 @@ namespace exception
//}
return x.tag_ != y.tag_;
}
template <class T>
class allocator2
{
public:
int tag_;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator2<U> other; };
explicit allocator2(int t = 0) : tag_(t)
{
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 default constructor.");
}
test::detail::tracker.allocator_ref();
}
allocator2(allocator<T> const& x) : tag_(x.tag_)
{
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 constructor from allocator.");
}
test::detail::tracker.allocator_ref();
}
template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
{
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 template copy constructor.");
}
test::detail::tracker.allocator_ref();
}
allocator2(allocator2 const& x) : tag_(x.tag_)
{
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 copy constructor.");
}
test::detail::tracker.allocator_ref();
}
~allocator2() {
test::detail::tracker.allocator_unref();
}
allocator2& operator=(allocator2 const& x) {
UNORDERED_SCOPE(allocator2::allocator2()) {
UNORDERED_EPOINT("Mock allocator2 assignment operator.");
tag_ = x.tag_;
}
return *this;
}
// If address throws, then it can't be used in erase or the
// destructor, which is very limiting. I need to check up on
// this.
pointer address(reference r) {
//UNORDERED_SCOPE(allocator2::address(reference)) {
// UNORDERED_EPOINT("Mock allocator2 address function.");
//}
return pointer(&r);
}
const_pointer address(const_reference r) {
//UNORDERED_SCOPE(allocator2::address(const_reference)) {
// UNORDERED_EPOINT("Mock allocator2 const address function.");
//}
return const_pointer(&r);
}
pointer allocate(size_type n) {
T* ptr = 0;
UNORDERED_SCOPE(allocator2::allocate(size_type)) {
UNORDERED_EPOINT("Mock allocator2 allocate function.");
using namespace std;
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
pointer allocate(size_type n, void const* u)
{
T* ptr = 0;
UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer)) {
UNORDERED_EPOINT("Mock allocator2 allocate function.");
using namespace std;
ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc();
}
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
}
void deallocate(pointer p, size_type n)
{
//::operator delete((void*) p);
if(p) {
test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
using namespace std;
free(p);
}
}
void construct(pointer p, T const& t) {
UNORDERED_SCOPE(allocator2::construct(T*, T)) {
UNORDERED_EPOINT("Mock allocator2 construct function.");
new(p) T(t);
}
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
UNORDERED_SCOPE(allocator2::construct(pointer, BOOST_FWD_REF(Args)...)) {
UNORDERED_EPOINT("Mock allocator2 construct function.");
new(p) T(boost::forward<Args>(args)...);
}
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#endif
void destroy(T* p) {
test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
}
size_type max_size() const {
UNORDERED_SCOPE(allocator2::construct(pointer, T)) {
UNORDERED_EPOINT("Mock allocator2 max_size function.");
}
return (std::numeric_limits<std::size_t>::max)();
}
typedef false_type propagate_on_container_copy_assignment;
typedef false_type propagate_on_container_move_assignment;
typedef false_type propagate_on_container_swap;
};
template <class T>
void swap(allocator2<T>& x, allocator2<T>& y)
{
std::swap(x.tag_, y.tag_);
}
// It's pretty much impossible to write a compliant swap when these
// two can throw. So they don't.
template <class T>
inline bool operator==(allocator2<T> const& x, allocator2<T> const& y)
{
//UNORDERED_SCOPE(operator==(allocator2, allocator2)) {
// UNORDERED_EPOINT("Mock allocator2 equality operator.");
//}
return x.tag_ == y.tag_;
}
template <class T>
inline bool operator!=(allocator2<T> const& x, allocator2<T> const& y)
{
//UNORDERED_SCOPE(operator!=(allocator2, allocator2)) {
// UNORDERED_EPOINT("Mock allocator2 inequality operator.");
//}
return x.tag_ != y.tag_;
}
}
}
+65 -32
View File
@@ -19,6 +19,12 @@
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
#else
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
#endif
namespace test
{
namespace minimal
@@ -26,10 +32,12 @@ namespace minimal
class destructible;
class copy_constructible;
class copy_constructible_equality_comparable;
class default_copy_constructible;
class default_assignable;
class assignable;
struct ampersand_operator_used {};
struct ampersand_operator_used {
ampersand_operator_used() { BOOST_TEST(false); }
};
template <class T> class hash;
template <class T> class equal_to;
@@ -48,6 +56,7 @@ namespace minimal
public:
destructible(constructor_param const&) {}
~destructible() {}
void dummy_member() const {}
private:
destructible(destructible const&);
destructible& operator=(destructible const&);
@@ -59,6 +68,7 @@ namespace minimal
copy_constructible(constructor_param const&) {}
copy_constructible(copy_constructible const&) {}
~copy_constructible() {}
void dummy_member() const {}
private:
copy_constructible& operator=(copy_constructible const&);
copy_constructible() {}
@@ -78,11 +88,15 @@ namespace minimal
{
}
void dummy_member() const {}
private:
copy_constructible_equality_comparable& operator=(
copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable() {}
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
bool operator==(
@@ -99,28 +113,34 @@ namespace minimal
return false;
}
class default_copy_constructible
class default_assignable
{
public:
default_copy_constructible(constructor_param const&) {}
default_assignable(constructor_param const&) {}
default_copy_constructible()
default_assignable()
{
}
default_copy_constructible(default_copy_constructible const&)
default_assignable(default_assignable const&)
{
}
~default_copy_constructible()
default_assignable& operator=(default_assignable const&)
{
return *this;
}
~default_assignable()
{
}
private:
default_copy_constructible& operator=(
default_copy_constructible const&);
void dummy_member() const {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
class assignable
@@ -130,11 +150,13 @@ namespace minimal
assignable(assignable const&) {}
assignable& operator=(assignable const&) { return *this; }
~assignable() {}
void dummy_member() const {}
private:
assignable() {}
// TODO: This messes up a concept check in the tests.
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
struct movable_init {};
@@ -148,11 +170,12 @@ namespace minimal
movable1() {}
explicit movable1(movable_init) {}
movable1(BOOST_RV_REF(movable1)) {}
movable1& operator=(BOOST_RV_REF(movable1));
movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
~movable1() {}
void dummy_member() const {}
};
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
class movable2
{
public:
@@ -160,6 +183,8 @@ namespace minimal
explicit movable2(movable_init) {}
movable2(movable2&&) {}
~movable2() {}
movable2& operator=(movable2&&) { return *this; }
void dummy_member() const {}
private:
movable2() {}
movable2(movable2 const&);
@@ -180,8 +205,10 @@ namespace minimal
~hash() {}
std::size_t operator()(T const&) const { return 0; }
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -195,8 +222,10 @@ namespace minimal
~equal_to() {}
bool operator()(T const&, T const&) const { return true; }
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T> class ptr;
@@ -284,9 +313,10 @@ namespace minimal
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -321,9 +351,10 @@ namespace minimal
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -367,8 +398,8 @@ namespace minimal
void construct(T* p, T const& t) { new((void*)p) T(t); }
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
new((void*)p) T(boost::forward<Args>(args)...);
}
#endif
@@ -383,8 +414,10 @@ namespace minimal
#else
private: allocator& operator=(allocator const&);
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
template <class T>
@@ -439,8 +472,8 @@ namespace minimal
void construct(T* p, T const& t) { new((void*)p) T(t); }
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
new((void*)p) T(boost::forward<Args>(args)...);
}
#endif
+362 -23
View File
@@ -18,15 +18,20 @@ 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 allocator;
template <class T> class allocator1;
template <class T> class allocator2;
object generate(object const*);
movable generate(movable const*);
implicitly_convertible generate(implicitly_convertible const*);
class object : private globally_counted_object
inline void ignore_variable(void const*) {}
class object : private counted_object
{
friend class hash;
friend class equal_to;
@@ -64,7 +69,82 @@ namespace test
}
};
class implicitly_convertible : private globally_counted_object
class movable : private counted_object
{
friend class hash;
friend class equal_to;
friend class less;
int tag1_, tag2_;
BOOST_COPYABLE_AND_MOVABLE(movable)
public:
explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {}
movable(movable const& x) :
counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{
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;
}
movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment
{
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;
}
~movable() {
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_;
}
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_;
}
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_);
}
friend movable generate(movable const*) {
int* x = 0;
return movable(generate(x), generate(x));
}
friend std::ostream& operator<<(std::ostream& out, movable const& o)
{
return out<<"("<<o.tag1_<<","<<o.tag2_<<")";
}
};
class implicitly_convertible : private counted_object
{
int tag1_, tag2_;
public:
@@ -78,6 +158,11 @@ namespace test
return object(tag1_, tag2_);
}
operator movable() const
{
return movable(tag1_, tag2_);
}
friend implicitly_convertible generate(implicitly_convertible const*) {
int* x = 0;
return implicitly_convertible(generate(x), generate(x));
@@ -89,6 +174,7 @@ namespace test
}
};
// Note: This is a deliberately bad hash function.
class hash
{
int type_;
@@ -106,6 +192,17 @@ namespace test
}
}
std::size_t operator()(movable const& x) const {
switch(type_) {
case 1:
return x.tag1_;
case 2:
return x.tag2_;
default:
return x.tag1_ + x.tag2_;
}
}
std::size_t operator()(int x) const {
return x;
}
@@ -123,6 +220,10 @@ namespace test
return hash()(x);
}
std::size_t hash_value(test::movable const& x) {
return hash()(x);
}
class less
{
int type_;
@@ -140,6 +241,17 @@ namespace test
}
}
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;
}
}
std::size_t operator()(int x1, int x2) const {
return x1 < x2;
}
@@ -166,6 +278,17 @@ namespace test
}
}
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;
}
}
std::size_t operator()(int x1, int x2) const {
return x1 == x2;
}
@@ -183,44 +306,253 @@ namespace test
}
};
// allocator1 only has the old fashioned 'construct' method and has
// a few less typedefs. allocator2 uses a custom pointer class.
template <class T>
class allocator
class allocator1
{
public:
int tag_;
typedef T value_type;
template <class U> struct rebind { typedef allocator1<U> other; };
explicit allocator1(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
template <class Y> allocator1(allocator1<Y> const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
allocator1(allocator1 const& x)
: tag_(x.tag_)
{
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* allocate(std::size_t n, void const* u)
{
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);
}
void construct(T* p, T const& t) {
// Don't count constructions here as it isn't always called.
//detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(t);
}
void destroy(T* p) {
//detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T();
// Work around MSVC buggy unused parameter warning.
ignore_variable(&p);
}
bool operator==(allocator1 const& x) const
{
return tag_ == x.tag_;
}
bool operator!=(allocator1 const& x) const
{
return tag_ != x.tag_;
}
enum {
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;
struct void_ptr
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T>
friend class ptr;
private:
#endif
void* ptr_;
public:
void_ptr() : ptr_(0) {}
template <typename T>
explicit void_ptr(ptr<T> const& x) : ptr_(x.ptr_) {}
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!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
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T>
friend class const_ptr;
private:
#endif
void* ptr_;
public:
void_const_ptr() : ptr_(0) {}
template <typename T>
explicit void_const_ptr(const_ptr<T> const& x) : ptr_(x.ptr_) {}
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!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
{
friend class allocator2<T>;
friend class const_ptr<T>;
friend struct void_ptr;
T* ptr_;
ptr(T* x) : ptr_(x) {}
public:
ptr() : ptr_(0) {}
explicit ptr(void_ptr const& x) : ptr_((T*) x.ptr_) {}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
ptr& operator++() { ++ptr_; return *this; }
ptr operator++(int) { 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_); }
T& operator[](std::ptrdiff_t s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
// I'm not using the safe bool idiom because the containers should be
// able to cope with bool conversions.
operator bool() const { return !!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_; }
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
{
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_) {}
explicit const_ptr(void_const_ptr const& x) : ptr_((T const*) x.ptr_) {}
T const& operator*() const { return *ptr_; }
T const* operator->() const { return ptr_; }
const_ptr& operator++() { ++ptr_; return *this; }
const_ptr operator++(int) { 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_); }
T const& operator[](int s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; }
operator bool() const { return !!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_; }
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
{
# ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public:
# else
template <class> friend class allocator;
template <class> friend class allocator2;
# endif
int tag_;
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef void_ptr void_pointer;
typedef void_const_ptr const_void_pointer;
typedef ptr<T> pointer;
typedef const_ptr<T> const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator<U> other; };
template <class U> struct rebind { typedef allocator2<U> other; };
explicit allocator(int t = 0) : tag_(t)
explicit allocator2(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
template <class Y> allocator(allocator<Y> const& x)
template <class Y> allocator2(allocator2<Y> const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
allocator(allocator const& x)
allocator2(allocator2 const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
~allocator()
~allocator2()
{
detail::tracker.allocator_unref();
}
@@ -236,9 +568,9 @@ namespace test
}
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 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* u)
@@ -250,8 +582,8 @@ namespace test
void deallocate(pointer p, size_type n)
{
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
::operator delete((void*) p);
detail::tracker.track_deallocate((void*) p.ptr_, n, sizeof(T), tag_);
::operator delete((void*) p.ptr_);
}
void construct(T* p, T const& t) {
@@ -259,8 +591,8 @@ namespace test
new(p) T(t);
}
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
template<class... Args> void construct(T* p, Args&&... args) {
#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)...);
}
@@ -275,12 +607,12 @@ namespace test
return (std::numeric_limits<size_type>::max)();
}
bool operator==(allocator const& x) const
bool operator==(allocator2 const& x) const
{
return tag_ == x.tag_;
}
bool operator!=(allocator const& x) const
bool operator!=(allocator2 const& x) const
{
return tag_ != x.tag_;
}
@@ -294,7 +626,14 @@ namespace test
};
template <class T>
bool equivalent_impl(allocator<T> const& x, allocator<T> const& y,
bool equivalent_impl(allocator1<T> const& x, allocator1<T> const& y,
test::derived_type)
{
return x == y;
}
template <class T>
bool equivalent_impl(allocator2<T> const& x, allocator2<T> const& y,
test::derived_type)
{
return x == y;
+3 -11
View File
@@ -11,13 +11,8 @@ project unordered-test/unordered
<toolset>intel:<warnings>on
# Would be nice to define -Wundef, but I'm getting warnings from
# Boost.Preprocessor on trunk.
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
#<toolset>gcc:<define>_GLIBCXX_DEBUG
#<toolset>darwin:<define>_GLIBCXX_DEBUG
#<toolset>msvc:<warnings-as-errors>on
<toolset>gcc:<warnings-as-errors>on
<toolset>darwin:<warnings-as-errors>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
;
test-suite unordered
@@ -28,6 +23,7 @@ test-suite unordered
[ run minimal_allocator.cpp ]
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run noexcept_tests.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
[ run incomplete_test.cpp ]
[ run simple_tests.cpp ]
@@ -37,9 +33,6 @@ test-suite unordered
[ run move_tests.cpp ]
[ run assign_tests.cpp ]
[ run insert_tests.cpp ]
[ run insert_tests.cpp : :
: <define>BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
: insert_deprecated ]
[ run insert_stable_tests.cpp ]
[ run unnecessary_copy_tests.cpp ]
[ run erase_tests.cpp ]
@@ -50,7 +43,6 @@ test-suite unordered
[ run load_factor_tests.cpp ]
[ run rehash_tests.cpp ]
[ run equality_tests.cpp ]
[ run equality_deprecated.cpp ]
[ run swap_tests.cpp ]
[ run compile_set.cpp : :
+28 -28
View File
@@ -3,10 +3,10 @@
// 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/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/limits.hpp>
// Boilerplate
@@ -90,16 +90,16 @@ void test_empty_allocator()
{
typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
BOOST_MPL_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
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);
@@ -128,16 +128,16 @@ void test_allocator1()
{
typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value));
#else
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
#endif
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
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);
@@ -174,11 +174,11 @@ void test_allocator2()
{
typedef allocator2<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, std::size_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, int*>));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, int const*>));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
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);
@@ -233,11 +233,11 @@ void test_allocator3()
{
typedef allocator3<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_MPL_ASSERT((boost::is_same<traits::size_type, unsigned short>));
BOOST_MPL_ASSERT((boost::is_same<traits::difference_type, std::ptrdiff_t>));
BOOST_MPL_ASSERT((boost::is_same<traits::pointer, ptr<int> >));
BOOST_MPL_ASSERT((boost::is_same<traits::const_pointer, ptr<int const> >));
BOOST_MPL_ASSERT((boost::is_same<traits::value_type, int>));
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);
+90 -18
View File
@@ -4,9 +4,9 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
@@ -22,11 +22,10 @@
namespace assign_tests {
test::seed_t seed(96785);
test::seed_t initialize_seed(96785);
template <class T>
void assign_tests1(T*,
test::random_generator generator = test::default_generator)
void assign_tests1(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
@@ -63,12 +62,12 @@ void assign_tests1(T*,
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 = test::default_generator)
void assign_tests2(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
@@ -87,9 +86,31 @@ void assign_tests2(T*,
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";
{
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());
}
std::cerr<<"assign_tests2.2\n";
@@ -110,22 +131,74 @@ void assign_tests2(T*,
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";
{
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());
}
std::cerr<<"assign_tests2.4\n";
{
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());
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
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,
test::allocator2<test::object> >* test_multiset;
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, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
@@ -178,6 +251,7 @@ UNORDERED_AUTO_TEST(check_traits)
}
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)
@@ -193,7 +267,7 @@ UNORDERED_TEST(assign_tests2, (
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
@@ -208,9 +282,7 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list) {
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
std::cerr<<"Initializer List Tests\n";
+12 -1
View File
@@ -4,29 +4,40 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <string>
namespace at_tests {
UNORDERED_AUTO_TEST(at_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x;
typedef boost::unordered_map<std::string, int>::iterator iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl;
x["one"] = 1;
x["two"] = 2;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check existing elements" << std::endl;
BOOST_TEST(x.at("one") == 1);
BOOST_TEST(x.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) {
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}
+25 -14
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <algorithm>
#include "../objects/test.hpp"
@@ -20,10 +21,10 @@
namespace bucket_tests {
test::seed_t seed(54635);
test::seed_t initialize_seed(54635);
template <class X>
void tests(X* = 0, test::random_generator generator = test::default_generator)
void tests(X*, test::random_generator generator)
{
test::check_instances check_;
@@ -67,20 +68,30 @@ void tests(X* = 0, test::random_generator generator = test::default_generator)
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
std::allocator<test::object> >* test_multimap_std_alloc;
UNORDERED_TEST(tests, ((test_set)(test_multiset)(test_map)(test_multimap)))
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,
test::allocator1<test::object> >* test_multiset;
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, test::equal_to,
test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(tests,
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
}
+18 -16
View File
@@ -7,8 +7,8 @@
// requirements. Makes sure everything compiles and is defined correctly.
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <iostream>
#include "../helpers/test.hpp"
@@ -32,13 +32,13 @@ template class boost::unordered_multimap<
template class boost::unordered_map<
test::minimal::assignable,
test::minimal::default_copy_constructible,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >;
template class boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >;
@@ -48,7 +48,7 @@ UNORDERED_AUTO_TEST(test0)
test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const,
test::minimal::copy_constructible> value_type;
test::minimal::assignable> value_type;
value_type value(x, x);
std::cout<<"Test unordered_map.\n";
@@ -62,7 +62,7 @@ UNORDERED_AUTO_TEST(test0)
boost::unordered_map<
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > map;
@@ -82,7 +82,7 @@ UNORDERED_AUTO_TEST(test0)
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible,
test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > multimap;
@@ -95,7 +95,7 @@ UNORDERED_AUTO_TEST(test0)
UNORDERED_AUTO_TEST(equality_tests) {
typedef std::pair<
test::minimal::copy_constructible_equality_comparable const,
test::minimal::copy_constructible> value_type;
test::minimal::copy_constructible_equality_comparable> value_type;
boost::unordered_map<int, int> int_map;
@@ -187,45 +187,47 @@ UNORDERED_AUTO_TEST(test2)
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
typedef std::pair<test::minimal::assignable const,
test::minimal::copy_constructible> map_value_type;
map_value_type map_value(assignable, copy_constructible);
test::minimal::assignable> map_value_type;
map_value_type map_value(assignable, assignable);
std::cout<<"Test unordered_map.\n";
boost::unordered_map<
test::minimal::assignable,
test::minimal::copy_constructible,
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, copy_constructible);
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_copy_constructible,
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_copy_constructible default_copy_constructible;
test::minimal::default_assignable default_assignable;
unordered_map_functions(map2, assignable, default_copy_constructible);
unordered_map_functions(map2, assignable, default_assignable);
std::cout<<"Test unordered_multimap.\n";
boost::unordered_multimap<
test::minimal::assignable,
test::minimal::copy_constructible,
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, copy_constructible);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
}
RUN_TESTS()
+3 -1
View File
@@ -7,8 +7,8 @@
// requirements. Makes sure everything compiles and is defined correctly.
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include <iostream>
#include "../helpers/test.hpp"
@@ -183,6 +183,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
std::cout<<"Test unordered_multiset.\n";
@@ -195,6 +196,7 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
}
UNORDERED_AUTO_TEST(movable1_tests)
+105 -44
View File
@@ -16,8 +16,7 @@
#pragma warning(pop)
#endif
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator/iterator_traits.hpp>
@@ -55,42 +54,38 @@ void container_test(X& r, T const&)
// value_type
BOOST_MPL_ASSERT((boost::is_same<T, value_type>));
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
boost::function_requires<boost::CopyConstructibleConcept<X> >();
// reference_type / const_reference_type
BOOST_MPL_ASSERT((boost::is_same<T&, reference>));
BOOST_MPL_ASSERT((boost::is_same<T const&, const_reference>));
BOOST_STATIC_ASSERT((boost::is_same<T&, reference>::value));
BOOST_STATIC_ASSERT((boost::is_same<T const&, const_reference>::value));
// iterator
boost::function_requires<boost::InputIteratorConcept<iterator> >();
BOOST_MPL_ASSERT((boost::is_same<T, iterator_value_type>));
BOOST_MPL_ASSERT((boost::is_convertible<iterator, const_iterator>));
BOOST_STATIC_ASSERT((boost::is_same<T, iterator_value_type>::value));
BOOST_STATIC_ASSERT((boost::is_convertible<iterator, const_iterator>::value));
// const_iterator
boost::function_requires<boost::InputIteratorConcept<const_iterator> >();
BOOST_MPL_ASSERT((boost::is_same<T, const_iterator_value_type>));
BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
// difference_type
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<difference_type>::is_signed>));
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<difference_type>::is_integer>));
BOOST_MPL_ASSERT((boost::is_same<difference_type,
iterator_difference_type>));
BOOST_MPL_ASSERT((boost::is_same<difference_type,
const_iterator_difference_type>));
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_signed);
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_integer);
BOOST_STATIC_ASSERT((boost::is_same<difference_type,
iterator_difference_type>::value));
BOOST_STATIC_ASSERT((boost::is_same<difference_type,
const_iterator_difference_type>::value));
// size_type
BOOST_MPL_ASSERT_NOT((boost::mpl::bool_<
std::numeric_limits<size_type>::is_signed>));
BOOST_MPL_ASSERT((boost::mpl::bool_<
std::numeric_limits<size_type>::is_integer>));
BOOST_STATIC_ASSERT(!std::numeric_limits<size_type>::is_signed);
BOOST_STATIC_ASSERT(std::numeric_limits<size_type>::is_integer);
// size_type can represent any non-negative value type of difference_type
// I'm not sure about either of these tests...
@@ -142,7 +137,7 @@ void unordered_destructible_test(X&)
X x1;
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x2(rvalue_default<X>());
X x3 = rvalue_default<X>();
// This can only be done if propagate_on_container_move_assignment::value
@@ -184,7 +179,29 @@ void unordered_set_test(X&, Key const&)
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_MPL_ASSERT((boost::is_same<value_type, key_type>));
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
}
template <class X, class Key, class T>
@@ -193,8 +210,32 @@ void unordered_map_test(X& r, Key const& k, T const& v)
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_MPL_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >));
BOOST_STATIC_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
// Calling functions
r.insert(std::pair<Key const, T>(k, v));
@@ -313,36 +354,36 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference;
BOOST_MPL_ASSERT((boost::is_same<Key, key_type>));
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
//boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
//boost::function_requires<boost::AssignableConcept<key_type> >();
BOOST_MPL_ASSERT((boost::is_same<Hash, hasher>));
BOOST_STATIC_ASSERT((boost::is_same<Hash, hasher>::value));
test::check_return_type<std::size_t>::equals(hf(k));
BOOST_MPL_ASSERT((boost::is_same<Pred, key_equal>));
BOOST_STATIC_ASSERT((boost::is_same<Pred, key_equal>::value));
test::check_return_type<bool>::convertible(eq(k, k));
boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
BOOST_MPL_ASSERT((boost::is_same<local_iterator_category,
iterator_category>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_difference,
iterator_difference>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_pointer,
iterator_pointer>));
BOOST_MPL_ASSERT((boost::is_same<local_iterator_reference,
iterator_reference>));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_category,
iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_difference,
iterator_difference>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_pointer,
iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<local_iterator_reference,
iterator_reference>::value));
boost::function_requires<
boost::InputIteratorConcept<const_local_iterator> >();
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_category,
const_iterator_category>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_difference,
const_iterator_difference>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_pointer,
const_iterator_pointer>));
BOOST_MPL_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_category,
const_iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_difference,
const_iterator_difference>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_pointer,
const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>::value));
X(10, hf, eq);
X a(10, hf, eq);
@@ -458,7 +499,7 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
X x1(rvalue_default<X>());
X x2(boost::move(x1));
x1 = rvalue_default<X>();
@@ -513,3 +554,23 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
sink(a8);
sink(a10);
}
template <class X, class T>
void unordered_set_member_test(X& x, T& t)
{
X x1(x);
x1.insert(t);
x1.begin()->dummy_member();
x1.cbegin()->dummy_member();
}
template <class X, class T>
void unordered_map_member_test(X& x, T& t)
{
X x1(x);
x1.insert(t);
x1.begin()->first.dummy_member();
x1.cbegin()->first.dummy_member();
x1.begin()->second.dummy_member();
x1.cbegin()->second.dummy_member();
}
+24 -22
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -17,11 +18,10 @@
namespace constructor_tests {
test::seed_t seed(356730);
test::seed_t initialize_seed(356730);
template <class T>
void constructor_tests1(T*,
test::random_generator generator = test::default_generator)
void constructor_tests1(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
@@ -172,8 +172,7 @@ void constructor_tests1(T*,
}
template <class T>
void constructor_tests2(T*,
test::random_generator const& generator = test::default_generator)
void constructor_tests2(T*, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
@@ -317,7 +316,7 @@ void constructor_tests2(T*,
test::check_equivalent_keys(x);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
std::cerr<<"Initializer list construct 1\n";
@@ -382,8 +381,7 @@ void constructor_tests2(T*,
}
template <class T>
void map_constructor_test(T* = 0,
test::random_generator const& generator = test::default_generator)
void map_constructor_test(T*, test::random_generator const& generator)
{
std::cerr<<"map_constructor_test\n";
@@ -401,24 +399,28 @@ void map_constructor_test(T* = 0,
test::check_equivalent_keys(x);
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
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,
test::allocator2<test::object> >* test_multiset;
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, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(constructor_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
@@ -428,10 +430,11 @@ UNORDERED_TEST(constructor_tests2,
)
UNORDERED_TEST(map_constructor_test,
((test_map)(test_multimap))
((test_map_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
@@ -442,8 +445,7 @@ UNORDERED_AUTO_TEST(test_default_initializer_list) {
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_initializer_list) {
std::cerr<<"Initializer List Tests\n";
+10 -12
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
@@ -15,14 +16,13 @@
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
test::seed_t seed(9063);
test::seed_t initialize_seed(9063);
namespace copy_tests
{
template <class T>
void copy_construct_tests1(T*,
test::random_generator const& generator = test::default_generator)
void copy_construct_tests1(T*, test::random_generator const& generator)
{
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
@@ -81,11 +81,8 @@ void copy_construct_tests1(T*,
}
template <class T>
void copy_construct_tests2(T* ptr,
test::random_generator const& generator = test::default_generator)
void copy_construct_tests2(T*, test::random_generator const& generator)
{
copy_construct_tests1(ptr);
BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
@@ -154,16 +151,16 @@ void copy_construct_tests2(T* ptr,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
@@ -207,6 +204,7 @@ UNORDERED_TEST(copy_construct_tests1, (
(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))
)
UNORDERED_TEST(copy_construct_tests2, (
-173
View File
@@ -1,173 +0,0 @@
// Copyright 2008-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)
#define BOOST_UNORDERED_DEPRECATED_EQUALITY
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
namespace equality_tests
{
struct mod_compare
{
bool alt_hash_;
explicit mod_compare(bool alt_hash = false) : alt_hash_(alt_hash) {}
bool operator()(int x, int y) const
{
return x % 1000 == y % 1000;
}
int operator()(int x) const
{
return alt_hash_ ? x % 250 : (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); \
}
#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); \
}
#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); \
}
#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); \
}
#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));
UNORDERED_AUTO_TEST(equality_size_tests)
{
boost::unordered_set<int> x1, x2;
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x1.insert(1);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
x2.insert(1);
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x2.insert(2);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
}
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_EQUALITY_MULTISET_TEST(
(1), !=, (501))
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(251), !=, (1)(501))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((251)(1))((1)(1)), !=, ((501)(1))((1)(1)))
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(501), ==, (1)(501))
UNORDERED_EQUALITY_SET_TEST(
(1)(501), ==, (501)(1))
}
UNORDERED_AUTO_TEST(equality_group_size_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(10)(20)(20), !=, (10)(10)(20))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((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)))
}
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_AUTO_TEST(equality_predicate_test)
{
UNORDERED_EQUALITY_SET_TEST(
(1), ==, (1001))
UNORDERED_EQUALITY_MAP_TEST(
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)))
}
// 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)
{
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));
BOOST_TEST(set1 == set2);
set1.insert(1); set2.insert(2);
BOOST_TEST(set1 != set2);
set1.insert(2); set2.insert(1);
BOOST_TEST(set1 == set2);
set1.insert(10); set2.insert(20);
BOOST_TEST(set1 != set2);
set1.insert(20); set2.insert(10);
BOOST_TEST(set1 == set2);
}
}
RUN_TESTS()
+10 -2
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
@@ -149,6 +150,14 @@ namespace equality_tests
((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
}
UNORDERED_AUTO_TEST(equality_multiple_group_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1)
);
}
// Test that equality still works when the two containers have
// different hash functions but the same equality predicate.
@@ -167,7 +176,6 @@ namespace equality_tests
set1.insert(20); set2.insert(10);
BOOST_TEST(set1 == set2);
}
}
RUN_TESTS()
+2 -1
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <algorithm>
#include <map>
+30 -3
View File
@@ -7,10 +7,12 @@
// hairy with several tricky edge cases - so explicitly test each one.
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../helpers/list.hpp"
#include "../helpers/invariants.hpp"
#include <set>
#include <iostream>
#include <iterator>
@@ -50,12 +52,21 @@ struct collision2_hash
int operator()(int x) const { return x & 1; }
};
// For testing erase in lots of buckets.
struct collision3_hash
{
int operator()(int x) const { return x; }
};
typedef boost::unordered_multimap<int, int,
collision_hash, std::equal_to<int>,
test::allocator<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::allocator<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;
typedef collide_map::value_type collide_value;
typedef test::list<collide_value> collide_list;
@@ -65,6 +76,7 @@ UNORDERED_AUTO_TEST(empty_range_tests)
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)
@@ -75,10 +87,13 @@ UNORDERED_AUTO_TEST(single_item_tests)
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)
@@ -91,6 +106,7 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
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);
}
{
@@ -99,6 +115,7 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
x.erase(x.begin(), boost::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);
}
{
@@ -107,6 +124,7 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
x.erase(boost::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);
}
}
@@ -128,6 +146,8 @@ bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
collide_list l(x.begin(), x.end());
l.erase(boost::next(l.begin(), start), boost::next(l.begin(), end));
x.erase(boost::next(x.begin(), start), boost::next(x.begin(), end));
test::check_equivalent_keys(x);
return compare(l, x);
}
@@ -190,4 +210,11 @@ UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
std::cout<<"\n";
}
UNORDERED_AUTO_TEST(exhaustive_collide3_tests)
{
std::cout<<"exhaustive_collide3_tests:\n";
exhaustive_erase_tests((collide_map3*) 0, 8, 4);
std::cout<<"\n";
}
RUN_TESTS()
+22 -8
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
@@ -14,17 +15,17 @@
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include <iostream>
namespace erase_tests
{
test::seed_t seed(85638);
test::seed_t initialize_seed(85638);
template <class Container>
void erase_tests1(Container*,
test::random_generator generator = test::default_generator)
void erase_tests1(Container*, test::random_generator generator)
{
std::cerr<<"Erase by key.\n";
{
@@ -32,6 +33,7 @@ void erase_tests1(Container*,
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)
{
@@ -41,6 +43,7 @@ void erase_tests1(Container*,
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);
}
}
@@ -51,6 +54,7 @@ void erase_tests1(Container*,
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
@@ -62,6 +66,7 @@ void erase_tests1(Container*,
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());
}
@@ -73,6 +78,7 @@ void erase_tests1(Container*,
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;
@@ -96,6 +102,7 @@ void erase_tests1(Container*,
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);
}
BOOST_TEST(x.empty());
}
@@ -116,12 +123,15 @@ void erase_tests1(Container*,
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);
}
std::cerr<<"quick_erase(begin()).\n";
@@ -131,6 +141,7 @@ void erase_tests1(Container*,
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
@@ -140,6 +151,7 @@ void erase_tests1(Container*,
--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());
}
@@ -151,6 +163,7 @@ void erase_tests1(Container*,
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;
@@ -174,6 +187,7 @@ void erase_tests1(Container*,
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);
}
BOOST_TEST(x.empty());
}
@@ -195,16 +209,16 @@ void erase_tests1(Container*,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
+9 -10
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -16,10 +17,10 @@
namespace find_tests
{
test::seed_t seed(78937);
test::seed_t initialize_seed(78937);
template <class X>
void find_tests1(X*, test::random_generator generator = test::default_generator)
void find_tests1(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
@@ -114,10 +115,8 @@ struct compatible_predicate
};
template <class X>
void find_compatible_keys_test(X*,
test::random_generator generator = test::default_generator)
void find_compatible_keys_test(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
value_iterator;
test::random_values<X> v(500, generator);
@@ -141,16 +140,16 @@ void find_compatible_keys_test(X*,
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
+1 -1
View File
@@ -4,8 +4,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered/unordered_map_fwd.hpp>
#include "../helpers/postfix.hpp"
template <typename T>
void call_swap(boost::unordered_map<T,T>& x,
+1 -1
View File
@@ -4,8 +4,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered/unordered_set_fwd.hpp>
#include "../helpers/postfix.hpp"
struct true_type { char x[100]; };
struct false_type { char x; };
+32 -27
View File
@@ -4,36 +4,36 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <utility>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
#include <utility>
namespace x
{
struct D { boost::unordered_map<D, D> x; };
}
namespace test
namespace incomplete_test
{
// Declare, but don't define some types.
struct value;
struct hash;
struct equals;
template <class T>
struct malloc_allocator;
template <class T> struct allocator;
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > map;
allocator<std::pair<value const, value> > > map;
typedef boost::unordered_multimap<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > multimap;
allocator<std::pair<value const, value> > > multimap;
typedef boost::unordered_set<value, hash, equals,
malloc_allocator<value> > set;
allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals,
malloc_allocator<value> > multiset;
allocator<value> > multiset;
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
@@ -48,12 +48,17 @@ namespace test
bool operator()(T const&, T const&) const { 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> {
allocator() {}
#include "../helpers/allocator.hpp"
template <typename T2>
allocator(const allocator<T2>& other) :
std::allocator<T>(other) {}
};
namespace test
{
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
@@ -61,19 +66,19 @@ namespace test
struct struct1 {
boost::unordered_map<struct1, struct1, hash, equals,
malloc_allocator<std::pair<struct1 const, struct1> > > x;
allocator<std::pair<struct1 const, struct1> > > x;
};
struct struct2 {
boost::unordered_multimap<struct2, struct2, hash, equals,
malloc_allocator<std::pair<struct2 const, struct2> > > x;
allocator<std::pair<struct2 const, struct2> > > x;
};
struct struct3 {
boost::unordered_set<struct3, hash, equals,
malloc_allocator<struct3> > x;
allocator<struct3> > x;
};
struct struct4 {
boost::unordered_multiset<struct4, hash, equals,
malloc_allocator<struct4> > x;
allocator<struct4> > x;
};
// Now define the value type.
@@ -82,15 +87,15 @@ namespace test
// Create some instances.
test::map m1;
test::multimap m2;
test::set s1;
test::multiset s2;
incomplete_test::map m1;
incomplete_test::multimap m2;
incomplete_test::set s1;
incomplete_test::multiset s2;
test::struct1 c1;
test::struct2 c2;
test::struct3 c3;
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.
@@ -112,7 +117,7 @@ namespace test
void use_types()
{
test::value x;
incomplete_test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
@@ -144,5 +149,5 @@ 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.
test::use_types();
incomplete_test::use_types();
}
+2 -1
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <iostream>
+215 -58
View File
@@ -4,10 +4,12 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/predef.h>
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -15,16 +17,16 @@
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/input_iterator.hpp"
#include "../helpers/helpers.hpp"
#include <iostream>
namespace insert_tests {
test::seed_t seed(243432);
test::seed_t initialize_seed(243432);
template <class X>
void unique_insert_tests1(X*,
test::random_generator generator = test::default_generator)
void unique_insert_tests1(X*, test::random_generator generator)
{
test::check_instances check_;
@@ -62,8 +64,7 @@ void unique_insert_tests1(X*,
}
template <class X>
void equivalent_insert_tests1(X*,
test::random_generator generator = test::default_generator)
void equivalent_insert_tests1(X*, test::random_generator generator)
{
std::cerr<<"insert(value) tests for containers with equivalent keys.\n";
@@ -96,8 +97,7 @@ void equivalent_insert_tests1(X*,
}
template <class X>
void insert_tests2(X*,
test::random_generator generator = test::default_generator)
void insert_tests2(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME test::ordered<X> tracker_type;
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
@@ -231,6 +231,24 @@ void insert_tests2(X*,
test::check_equivalent_keys(x);
}
std::cerr<<"insert range with rehash tests.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v(1000, generator);
x.insert(*v.begin());
x.clear();
x.insert(v.begin(), v.end());
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr<<"insert input iterator range tests.\n";
{
@@ -260,13 +278,25 @@ void insert_tests2(X*,
test::check_equivalent_keys(x);
}
std::cerr<<"insert copy iterator range test 2.\n";
{
test::check_instances check_;
X x;
test::random_values<X> v1(500, generator);
test::random_values<X> v2(500, generator);
x.insert(test::copy_iterator(v1.begin()), test::copy_iterator(v1.end()));
x.insert(test::copy_iterator(v2.begin()), test::copy_iterator(v2.end()));
test::check_equivalent_keys(x);
}
}
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class X>
void unique_emplace_tests1(X*,
test::random_generator generator = test::default_generator)
void unique_emplace_tests1(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef test::ordered<X> ordered;
@@ -302,8 +332,7 @@ void unique_emplace_tests1(X*,
}
template <class X>
void equivalent_emplace_tests1(X*,
test::random_generator generator = test::default_generator)
void equivalent_emplace_tests1(X*, test::random_generator generator)
{
std::cerr<<"emplace(value) tests for containers with equivalent keys.\n";
@@ -332,10 +361,73 @@ void equivalent_emplace_tests1(X*,
test::check_equivalent_keys(x);
}
#endif
template <class X>
void move_emplace_tests(X*, test::random_generator generator)
{
std::cerr<<"emplace(move(value)) tests for containers with unique keys.\n";
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it)
{
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
typename X::value_type value = *it;
x.emplace(boost::move(value));
tracker.insert(*it);
tracker.compare_key(x, *it);
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
tracker.compare(x);
}
template <class X>
void map_tests(X*, test::random_generator generator = test::default_generator)
void default_emplace_tests(X*, test::random_generator)
{
std::cerr<<"emplace() tests.\n";
bool is_unique = test::has_unique_keys<X>::value;
X x;
x.emplace();
BOOST_TEST(x.size() == 1);
x.emplace();
BOOST_TEST(x.size() == is_unique ? 1: 2);
x.emplace();
BOOST_TEST(x.size() == is_unique ? 1: 3);
typename X::value_type y;
BOOST_TEST(x.count(test::get_key<X>(y)) == is_unique ? 1: 3);
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
x.emplace(y);
BOOST_TEST(x.size() == is_unique ? 1: 4);
BOOST_TEST(x.count(test::get_key<X>(y)) == is_unique ? 1: 4);
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
x.clear();
BOOST_TEST(x.empty());
x.emplace(y);
BOOST_TEST(x.size() == 1);
x.emplace(y);
BOOST_TEST(x.size() == is_unique ? 1: 2);
BOOST_TEST(x.count(test::get_key<X>(y)) == is_unique ? 1: 2);
BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
}
template <class X>
void map_tests(X*, test::random_generator generator)
{
std::cerr<<"map tests.\n";
@@ -365,8 +457,7 @@ void map_tests(X*, test::random_generator generator = test::default_generator)
// value type.
template <class X>
void map_insert_range_test1(X*,
test::random_generator generator = test::default_generator)
void map_insert_range_test1(X*, test::random_generator generator)
{
std::cerr<<"map_insert_range_test1\n";
@@ -387,8 +478,7 @@ void map_insert_range_test1(X*,
}
template <class X>
void map_insert_range_test2(X*,
test::random_generator generator = test::default_generator)
void map_insert_range_test2(X*, test::random_generator generator)
{
std::cerr<<"map_insert_range_test2\n";
@@ -407,48 +497,65 @@ void map_insert_range_test2(X*,
test::check_equivalent_keys(x);
}
boost::unordered_set<test::object,
boost::unordered_set<test::movable,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::movable,
test::hash, test::equal_to,
test::allocator2<test::movable> >* test_multiset;
boost::unordered_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;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(unique_insert_tests1,
((test_set)(test_map))
((test_set_std_alloc)(test_set)(test_map))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_insert_tests1,
((test_multiset)(test_multimap))
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(insert_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
UNORDERED_TEST(unique_emplace_tests1,
((test_set)(test_map))
((test_set_std_alloc)(test_set)(test_map))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(equivalent_emplace_tests1,
((test_multiset)(test_multimap))
((test_multimap_std_alloc)(test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(move_emplace_tests,
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
(test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(default_emplace_tests,
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)
(test_multiset)(test_multimap))
((default_generator)(generate_collisions))
)
#endif
UNORDERED_TEST(map_tests,
((test_map))
@@ -456,17 +563,31 @@ UNORDERED_TEST(map_tests,
)
UNORDERED_TEST(map_insert_range_test1,
((test_map)(test_multimap))
((test_multimap_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_insert_range_test2,
((test_map)(test_multimap))
((test_multimap_std_alloc)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
struct initialize_from_two_ints
{
int a, b;
friend std::size_t hash_value(initialize_from_two_ints const& x)
{
return x.a + x.b;
}
bool operator==(initialize_from_two_ints const& x) const
{
return a == x.a && b == x.b;
}
};
UNORDERED_AUTO_TEST(insert_initializer_list_set)
{
@@ -475,8 +596,38 @@ UNORDERED_AUTO_TEST(insert_initializer_list_set)
BOOST_TEST_EQ(set.size(), 3u);
BOOST_TEST(set.find(1) != set.end());
BOOST_TEST(set.find(4) == set.end());
boost::unordered_set<initialize_from_two_ints> set2;
#if BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4,5,0)
set2.insert({{1, 2}});
#else
set2.insert({1, 2});
#endif
BOOST_TEST(set2.size() == 1);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({2,1}) == set2.end());
set2.insert({{3,4},{5,6},{7,8}});
BOOST_TEST(set2.size() == 4);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({3,4}) != set2.end());
BOOST_TEST(set2.find({5,6}) != set2.end());
BOOST_TEST(set2.find({7,8}) != set2.end());
BOOST_TEST(set2.find({8,7}) == set2.end());
set2.insert({{2, 1}, {3,4}});
BOOST_TEST(set2.size() == 5);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({2,1}) != set2.end());
BOOST_TEST(set2.find({3,4}) != set2.end());
BOOST_TEST(set2.find({5,6}) != set2.end());
BOOST_TEST(set2.find({7,8}) != set2.end());
BOOST_TEST(set2.find({8,7}) == set2.end());
}
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
{
boost::unordered_multiset<std::string> multiset;
@@ -493,6 +644,8 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
BOOST_TEST_EQ(multiset.count("c"), 0u);
}
#endif
UNORDERED_AUTO_TEST(insert_initializer_list_map)
{
boost::unordered_map<std::string, std::string> map;
@@ -516,8 +669,8 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
struct overloaded_constructor
{
overloaded_constructor(int x1 = 1, int x2 = 2, int x3 = 3, int x4 = 4)
: x1(x1), x2(x2), x3(x3), x4(x4) {}
overloaded_constructor(int x1_ = 1, int x2_ = 2, int x3_ = 3, int x4_ = 4)
: x1(x1_), x2(x2_), x3(x3_), x4(x4_) {}
int x1, x2, x3, x4;
@@ -550,20 +703,6 @@ UNORDERED_AUTO_TEST(map_emplace_test)
x.emplace(2, 3);
BOOST_TEST(x.find(2) != x.end() &&
x.find(2)->second == overloaded_constructor(3));
#if defined (BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT)
x.emplace(1);
BOOST_TEST(x.find(1) != x.end() &&
x.find(1)->second == overloaded_constructor());
x.emplace(4, 5, 6);
BOOST_TEST(x.find(4) != x.end() &&
x.find(4)->second == overloaded_constructor(5, 6));
x.emplace(7, 8, 9, 10);
BOOST_TEST(x.find(7) != x.end() &&
x.find(7)->second == overloaded_constructor(8, 9, 10));
#endif
}
UNORDERED_AUTO_TEST(set_emplace_test)
@@ -597,6 +736,19 @@ UNORDERED_AUTO_TEST(set_emplace_test)
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
struct derived_from_piecewise_construct_t :
boost::unordered::piecewise_construct_t {};
derived_from_piecewise_construct_t piecewise_rvalue() {
return derived_from_piecewise_construct_t();
}
struct convertible_to_piecewise {
operator boost::unordered::piecewise_construct_t() const {
return boost::unordered::piecewise_construct;
}
};
UNORDERED_AUTO_TEST(map_emplace_test2)
{
boost::unordered_map<overloaded_constructor, overloaded_constructor> x;
@@ -605,13 +757,18 @@ UNORDERED_AUTO_TEST(map_emplace_test2)
BOOST_TEST(x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second == overloaded_constructor());
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1), boost::make_tuple());
x.emplace(convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second == overloaded_constructor());
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(2,3), boost::make_tuple(4,5,6));
x.emplace(piecewise_rvalue(), boost::make_tuple(2,3), boost::make_tuple(4,5,6));
BOOST_TEST(x.find(overloaded_constructor(2,3)) != x.end() &&
x.find(overloaded_constructor(2,3))->second == overloaded_constructor(4,5,6));
derived_from_piecewise_construct_t d;
x.emplace(d, boost::make_tuple(9,3,1), boost::make_tuple(10));
BOOST_TEST(x.find(overloaded_constructor(9,3,1)) != x.end() &&
x.find(overloaded_constructor(9,3,1))->second == overloaded_constructor(10));
}
UNORDERED_AUTO_TEST(set_emplace_test2)
+1 -1
View File
@@ -4,9 +4,9 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
void foo(boost::unordered_set<int>&,
boost::unordered_map<int, int>&,
+1 -1
View File
@@ -4,9 +4,9 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
void foo(boost::unordered_set<int>& x1,
boost::unordered_map<int, int>& x2,
+17 -11
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/limits.hpp>
#include "../helpers/random_values.hpp"
@@ -19,10 +20,10 @@
namespace load_factor_tests
{
test::seed_t seed(783656);
test::seed_t initialize_seed(783656);
template <class X>
void set_load_factor_tests(X* = 0)
void set_load_factor_tests(X*)
{
X x;
@@ -36,8 +37,7 @@ void set_load_factor_tests(X* = 0)
}
template <class X>
void insert_test(X*, float mlf,
test::random_generator generator = test::default_generator)
void insert_test(X*, float mlf, test::random_generator generator)
{
X x;
x.max_load_factor(mlf);
@@ -57,16 +57,18 @@ void insert_test(X*, float mlf,
}
template <class X>
void load_factor_insert_tests(X* ptr = 0)
void load_factor_insert_tests(X* ptr, test::random_generator generator)
{
insert_test(ptr, 1.0f);
insert_test(ptr, 0.1f);
insert_test(ptr, 100.0f);
insert_test(ptr, 1.0f, generator);
insert_test(ptr, 0.1f, generator);
insert_test(ptr, 100.0f, generator);
insert_test(ptr, (std::numeric_limits<float>::min)());
insert_test(ptr, (std::numeric_limits<float>::min)(),
generator);
if(std::numeric_limits<float>::has_infinity)
insert_test(ptr, std::numeric_limits<float>::infinity());
insert_test(ptr, std::numeric_limits<float>::infinity(),
generator);
}
boost::unordered_set<int>* int_set_ptr;
@@ -74,12 +76,16 @@ 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;
UNORDERED_TEST(set_load_factor_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
}
+13 -13
View File
@@ -3,10 +3,10 @@
// 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/detail/allocator_helpers.hpp>
#include <boost/unordered/detail/allocate.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/static_assert.hpp>
#include "../objects/test.hpp"
template <class Tp>
@@ -41,22 +41,22 @@ void test_simple_allocator()
typedef boost::unordered::detail::allocator_traits<
SimpleAllocator<T> > traits;
BOOST_MPL_ASSERT((boost::is_same<typename traits::allocator_type, SimpleAllocator<T> >));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type, SimpleAllocator<T> >::value));
BOOST_MPL_ASSERT((boost::is_same<typename traits::value_type, T>));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::value_type, T>::value));
BOOST_MPL_ASSERT((boost::is_same<typename traits::pointer, T* >));
BOOST_MPL_ASSERT((boost::is_same<typename traits::const_pointer, T const*>));
//BOOST_MPL_ASSERT((boost::is_same<typename traits::void_pointer, void* >));
//BOOST_MPL_ASSERT((boost::is_same<typename traits::const_void_pointer, void const*>));
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_MPL_ASSERT((boost::is_same<typename traits::difference_type, std::ptrdiff_t>));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>));
#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));
#else
BOOST_MPL_ASSERT((boost::is_same<typename traits::size_type, std::size_t>));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type, std::size_t>::value));
#endif
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
+34 -24
View File
@@ -4,9 +4,10 @@
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
@@ -21,8 +22,8 @@
namespace move_tests
{
test::seed_t seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_RVALUE_REFERENCES)
test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
@@ -56,8 +57,7 @@ namespace move_tests
}
template <class T>
void move_construct_tests1(T* ptr,
test::random_generator const& generator = test::default_generator)
void move_construct_tests1(T* ptr, test::random_generator const& generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
@@ -90,8 +90,7 @@ namespace move_tests
}
template <class T>
void move_assign_tests1(T*,
test::random_generator const& generator = test::default_generator)
void move_assign_tests1(T*, test::random_generator const& generator)
{
{
test::check_instances check_;
@@ -109,8 +108,7 @@ namespace move_tests
}
template <class T>
void move_construct_tests2(T*,
test::random_generator const& generator = test::default_generator)
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);
@@ -156,17 +154,21 @@ namespace move_tests
test::random_values<T> v(25, generator);
T y(create(v, count, hf, eq, al, 1.0), al);
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(count == test::global_object_count);
#elif defined(BOOST_HAS_NRVO)
BOOST_TEST(
test::global_object_count.constructions - count.constructions <=
(test::is_map<T>::value ? 50 : 25));
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(
test::global_object_count.constructions - count.constructions <=
(test::is_map<T>::value ? 100 : 50));
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);
@@ -179,8 +181,7 @@ namespace move_tests
}
template <class T>
void move_assign_tests2(T*,
test::random_generator const& generator = test::default_generator)
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);
@@ -315,18 +316,22 @@ namespace move_tests
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
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,
test::allocator1<test::object> >* test_multiset;
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, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
@@ -366,16 +371,20 @@ boost::unordered_multimap<test::object, test::object,
using test::generate_collisions;
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))
)
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))
)
UNORDERED_TEST(move_construct_tests2, (
(test_set)(test_multiset)(test_map)(test_multimap)
@@ -389,6 +398,7 @@ boost::unordered_multimap<test::object, test::object,
(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))
)
}
+125
View File
@@ -0,0 +1,125 @@
// Copyright 2013 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/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
namespace noexcept_tests
{
// Test the noexcept is set correctly for the move constructor.
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&) {}
};
UNORDERED_AUTO_TEST(test_noexcept)
{
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
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));
#endif
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));
}
// 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();
}
}
class hash_nothrow_move : boost::hash<int>
{
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
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=(hash_nothrow_move const&)
{ test_throw("Assign"); return *this; }
std::size_t operator()(int x) const
{ test_throw("Operator"); return static_cast<base const&>(*this)(x); }
};
class equal_to_nothrow_move : std::equal_to<int>
{
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)
typedef std::equal_to<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=(equal_to_nothrow_move const&)
{ test_throw("Assign"); return *this; }
std::size_t operator()(int x, int y) const
{ test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
};
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
{
typedef boost::unordered_set<int,
hash_nothrow_move, equal_to_nothrow_move> throwing_set;
if (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;
}
}
}
RUN_TESTS()
+141 -16
View File
@@ -4,17 +4,20 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/metafunctions.hpp"
#include "../objects/test.hpp"
namespace rehash_tests
{
test::seed_t seed(2974);
test::seed_t initialize_seed(2974);
template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
@@ -25,7 +28,7 @@ bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
}
template <class X>
void rehash_empty_test1(X* = 0)
void rehash_empty_test1(X*)
{
X x;
@@ -34,11 +37,13 @@ void rehash_empty_test1(X* = 0)
x.rehash(0);
BOOST_TEST(postcondition(x, 0));
x.rehash(10000000);
BOOST_TEST(postcondition(x, 10000000));
}
template <class X>
void rehash_empty_test2(X* = 0,
test::random_generator generator = test::default_generator)
void rehash_empty_test2(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -53,11 +58,14 @@ void rehash_empty_test2(X* = 0,
tracker.compare(x);
BOOST_TEST(postcondition(x, 10000));
x.rehash(10000000);
tracker.compare(x);
BOOST_TEST(postcondition(x, 10000000));
}
template <class X>
void rehash_empty_test3(X* = 0,
test::random_generator generator = test::default_generator)
void rehash_empty_test3(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -74,10 +82,8 @@ void rehash_empty_test3(X* = 0,
BOOST_TEST(postcondition(x, 0));
}
template <class X>
void rehash_test1(X* = 0,
test::random_generator generator = test::default_generator)
void rehash_test1(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
@@ -99,22 +105,141 @@ void rehash_test1(X* = 0,
tracker.compare(x);
}
template <class X>
void reserve_empty_test1(X*)
{
X x;
x.reserve(10000);
BOOST_TEST(x.bucket_count() >= 10000);
x.reserve(0);
x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 10000000);
}
template <class X>
void reserve_empty_test2(X*)
{
X x;
x.max_load_factor(0.25);
x.reserve(10000);
BOOST_TEST(x.bucket_count() >= 40000);
x.reserve(0);
x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 40000000);
}
template <class X>
void reserve_test1(X*, test::random_generator generator)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (int 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());
X x;
x.max_load_factor(random_mlf ?
static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
// For the current standard this should reserve i+1, I've
// submitted a defect report and will assume it's a defect
// for now.
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;
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)
{
for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
{
for (int 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());
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());
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);
}
}
}
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_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,
test::allocator2<test::movable> >* test_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(reserve_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(reserve_empty_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(reserve_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))
((default_generator)(generate_collisions))
)
}
+2 -1
View File
@@ -6,9 +6,10 @@
// This test checks the runtime requirements of containers.
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <cstdlib>
#include <algorithm>
+35 -23
View File
@@ -4,12 +4,13 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include <boost/config.hpp>
#include <algorithm>
#include <iterator>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
@@ -24,7 +25,7 @@
namespace swap_tests
{
test::seed_t seed(783472);
test::seed_t initialize_seed(783472);
template <class X>
void swap_test_impl(X& x1, X& x2)
@@ -39,7 +40,7 @@ void swap_test_impl(X& x1, X& x2)
}
template <class X>
void swap_tests1(X*, test::random_generator generator = test::default_generator)
void swap_tests1(X*, test::random_generator generator)
{
{
test::check_instances check_;
@@ -75,10 +76,9 @@ void swap_tests1(X*, test::random_generator generator = test::default_generator)
}
template <class X>
void swap_tests2(X* ptr = 0,
test::random_generator generator = test::default_generator)
void swap_tests2(X* ptr, test::random_generator generator)
{
swap_tests1(ptr);
swap_tests1(ptr, generator);
typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal;
@@ -147,18 +147,22 @@ void swap_tests2(X* ptr = 0,
}
}
boost::unordered_set<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_set;
boost::unordered_multiset<test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_map;
std::allocator<test::object> >* test_map_std_alloc;
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,
test::allocator2<test::object> >* test_multiset;
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, test::equal_to,
test::allocator<test::object> >* test_multimap;
test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object,
test::hash, test::equal_to,
@@ -200,6 +204,9 @@ bool is_propagate(T*)
return T::allocator_type::is_propagate_on_swap;
}
using test::default_generator;
using test::generate_collisions;
UNORDERED_AUTO_TEST(check_traits)
{
BOOST_TEST(!is_propagate(test_set));
@@ -208,16 +215,21 @@ UNORDERED_AUTO_TEST(check_traits)
}
UNORDERED_TEST(swap_tests1, (
(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)
))
(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))
)
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)
))
(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))
)
}
RUN_TESTS()
+116 -49
View File
@@ -1,30 +1,15 @@
#include <iostream>
// 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 "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include "../helpers/postfix.hpp"
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
# elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
# elif defined(_LIBCPP_VERSION)
# define BOOST_UNORDERED_VARIADIC_MOVE
# elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# if defined(__GLIBCXX__) && __GLIBCXX__ >= 20090804
# define BOOST_UNORDERED_VARIADIC_MOVE
# endif
# elif defined(__STL_CONFIG_H)
# elif defined(__MSL_CPP__)
# elif defined(__IBMCPP__)
# elif defined(MSIPL_COMPILE_H)
# elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
# endif
#endif
#include <iostream>
#include "../helpers/test.hpp"
namespace unnecessary_copy_tests
{
@@ -35,8 +20,17 @@ namespace unnecessary_copy_tests
public:
static int copies;
static int moves;
count_copies() : tag_(0) { ++copies; }
explicit count_copies(int tag) : tag_(tag) { ++copies; }
static int id_count;
count_copies() : tag_(0), id_(++id_count) {
++copies;
trace_op("Default construct");
}
explicit count_copies(int tag) : tag_(tag), id_(++id_count) {
++copies;
trace_op("Tag construct");
}
// This bizarre constructor is an attempt to confuse emplace.
//
@@ -48,17 +42,30 @@ namespace unnecessary_copy_tests
// The second emplace should use the single argument contructor for
// the key, and this constructor for the value.
count_copies(count_copies const&, count_copies const& x)
: tag_(x.tag_) { ++copies; }
: tag_(x.tag_), id_(++id_count)
{
++copies;
trace_op("Pair construct");
}
count_copies(count_copies const& x) : tag_(x.tag_) { ++copies; }
count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_) {
count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count)
{
++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");
}
count_copies& operator=(BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
{
tag_ = p.tag_;
++copies;
trace_op("Copy assign");
return *this;
}
@@ -66,10 +73,21 @@ namespace unnecessary_copy_tests
{
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;
}
int tag_;
int id_;
};
bool operator==(count_copies const& x, count_copies const& y) {
@@ -84,6 +102,9 @@ namespace unnecessary_copy_tests
void reset() {
count_copies::copies = 0;
count_copies::moves = 0;
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "\nReset\n" << std::endl;
}
}
@@ -98,6 +119,20 @@ namespace unnecessary_copy_tests
}
}
// Boost.Move doesn't seem to work very well on this compiler.
// For example for:
//
// T x;
//
// It will default construct T, and then move it in.
// For 'T const' it seems to copy.
#if defined(__IBMCPP__) && __IBMCPP__ <= 1210
#define EXTRA_CONSTRUCT_COST 1
#else
#define EXTRA_CONSTRUCT_COST 0
#endif
#define COPY_COUNT(n) \
if(::unnecessary_copy_tests::count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \
@@ -129,14 +164,19 @@ namespace unnecessary_copy_tests
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::copies \
<< ::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;
template <class T>
void unnecessary_copy_insert_test(T*)
@@ -173,7 +213,7 @@ namespace unnecessary_copy_tests
reset();
T x;
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1);
#else
COPY_COUNT(2);
@@ -185,9 +225,9 @@ namespace unnecessary_copy_tests
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
((set)(multiset)(map)(multimap)))
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T>
void unnecessary_copy_emplace_move_test(T*)
void unnecessary_copy_emplace_std_move_test(T*)
{
reset();
T x;
@@ -197,10 +237,29 @@ namespace unnecessary_copy_tests
COPY_COUNT(1); MOVE_COUNT(1);
}
UNORDERED_TEST(unnecessary_copy_emplace_move_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*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a));
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1); MOVE_COUNT(1);
#else
// Since std::pair isn't movable, move only works for sets.
COPY_COUNT_RANGE(1, 2); MOVE_COUNT_RANGE(0, 1);
#endif
}
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_test,
((set)(multiset)(map)(multimap)))
template <class T>
void unnecessary_copy_emplace_boost_move_set_test(T*)
{
@@ -222,10 +281,10 @@ namespace unnecessary_copy_tests
T x;
COPY_COUNT(0); MOVE_COUNT(0);
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT(0);
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a));
#if defined(BOOST_NO_RVALUE_REFERENCES)
COPY_COUNT(2); MOVE_COUNT(0);
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(2); MOVE_COUNT_EXTRA(0, 1);
#else
COPY_COUNT(1); MOVE_COUNT(1);
#endif
@@ -260,7 +319,8 @@ namespace unnecessary_copy_tests
// the existing element.
reset();
x.emplace();
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#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
@@ -284,14 +344,16 @@ namespace unnecessary_copy_tests
x.emplace(source<count_copies>());
COPY_COUNT(1); MOVE_COUNT(source_cost);
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
// No move should take place.
reset();
x.emplace(std::move(a));
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
// Just in case a did get moved...
// Use a new value for cases where a did get moved...
count_copies b;
// The container will have to create a copy in order to compare with
@@ -336,7 +398,7 @@ namespace unnecessary_copy_tests
// TODO: Run tests for pairs without const etc.
std::pair<count_copies const, count_copies> a;
x.emplace(a);
COPY_COUNT(4); MOVE_COUNT(0);
COPY_COUNT_EXTRA(4, 1); MOVE_COUNT_EXTRA(0, 1);
//
// 0 arguments
@@ -346,7 +408,16 @@ namespace unnecessary_copy_tests
// COPY_COUNT(1) would be okay here.
reset();
x.emplace();
COPY_COUNT(2); MOVE_COUNT(0);
# if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
// This is a little odd, Visual C++ 11 seems to move the pair, which
// results in one copy (for the const key) and one move (for the
// non-const mapped value). Since 'emplace(boost::move(a))' (see below)
// has the normal result, it must be some odd consequence of how
// Visual C++ 11 handles calling move for default arguments.
COPY_COUNT(3); MOVE_COUNT(1);
# else
COPY_COUNT_EXTRA(2, 1); MOVE_COUNT_EXTRA(0, 1);
# endif
#endif
reset();
@@ -370,9 +441,8 @@ namespace unnecessary_copy_tests
x.emplace(source<std::pair<count_copies, count_copies> >());
COPY_COUNT(2); MOVE_COUNT(source_pair_cost);
#if (defined(__GNUC__) && __GNUC__ > 4) || \
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 )
#if !(defined(__GNUC__) && __cplusplus < 199900L) && \
!(defined(_MSC_VER) && _MSC_VER < 1600)
count_copies part;
reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
@@ -381,16 +451,12 @@ namespace unnecessary_copy_tests
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
// No move should take place.
// (since a is already in the container)
reset();
x.emplace(std::move(a));
x.emplace(boost::move(a));
COPY_COUNT(0); MOVE_COUNT(0);
#endif
//
// 2 arguments
//
@@ -420,7 +486,7 @@ namespace unnecessary_copy_tests
boost::make_tuple(boost::ref(b.second)));
COPY_COUNT(0); MOVE_COUNT(0);
#if !defined(BOOST_NO_0X_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_HAS_TR1_TUPLE)
reset();
x.emplace(boost::unordered::piecewise_construct,
@@ -443,8 +509,9 @@ namespace unnecessary_copy_tests
COPY_COUNT(tuple_copy_cost);
MOVE_COUNT(tuple_move_cost);
#if defined(__GNUC__) && __GNUC__ > 4 || \
defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
!(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),