Compare commits

...

42 Commits

Author SHA1 Message Date
Beman Dawes 571e2632f2 Release 1.45.0
[SVN r66646]
2010-11-19 15:17:53 +00:00
Daniel James dc8e65043b Merge fix for unordered container insertion bug.
[SVN r66151]
2010-10-23 12:02:18 +00:00
Daniel James 8b4c480d47 Merge unordered build and documentation tweaks.
[SVN r63503]
2010-07-01 21:42:52 +00:00
Daniel James 70ca44b503 Merge unordered.
[SVN r62610]
2010-06-08 23:23:43 +00:00
Daniel James 795d9f0aa7 Support for clang.
[SVN r61640]
2010-04-28 08:23:41 +00:00
Daniel James ec97640b1b Merge some link fixes and release notes.
[SVN r61474]
2010-04-21 23:00:35 +00:00
Daniel James d3ca85bdbd Merge throw_exception use in unordered.
[SVN r61063]
2010-04-05 08:08:25 +00:00
Daniel James fe2a6c521b Merge from trunk.
- Add `quick_erase` for unordered. `erase_return_void` is now deprecated.
   Fixes #3966
 - Avoid collision between 0 and 0.5. Fixes #4038


[SVN r60980]
2010-03-31 21:39:07 +00:00
Daniel James 958738c7af Merge a warning fix for unordered.
[SVN r60668]
2010-03-17 00:34:26 +00:00
Daniel James 3fb7d15f5b Merge hash and unordered from trunk.
- Replace uses of deprecated C++0x macros
 - Set length of primes inside template on Sun C++. Fixes #3854
 - Missing newline at end of file.



[SVN r59911]
2010-02-25 19:05:01 +00:00
Daniel James 2b212d7c49 Merge unordered documentation.
[SVN r58844]
2010-01-09 17:17:53 +00:00
Daniel James aa0e8eedd2 Merge unordered changes.
[SVN r58802]
2010-01-08 05:39:54 +00:00
Daniel James f962857e68 Merge unordered.
[SVN r58605]
2009-12-30 22:17:48 +00:00
Daniel James 02bf8f288e Merge unordered and hash.
Improved Codegear support in unordered.
Another warning suppression in hash.


[SVN r58223]
2009-12-07 19:26:26 +00:00
Daniel James 144d8963a3 Merge unordered.
Warning fixes, support for incomplete types and tweak some test.


[SVN r57998]
2009-11-28 11:40:08 +00:00
Daniel James f709c16d70 Merge [56844]: Correct macro checks for initializer lists.
[SVN r57801]
2009-11-20 09:16:36 +00:00
Daniel James a3e57838ed Merged revisions 57126,57139,57150-57153 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r57126 | danieljames | 2009-10-24 12:56:30 +0100 (Sat, 24 Oct 2009) | 1 line
  
  Update the intel compile flags.
........
  r57139 | danieljames | 2009-10-24 18:53:03 +0100 (Sat, 24 Oct 2009) | 1 line
  
  Fix unordered for intel strict.
........
  r57150 | danieljames | 2009-10-25 10:54:28 +0000 (Sun, 25 Oct 2009) | 1 line
  
  Fix the intel strict flag.
........
  r57151 | danieljames | 2009-10-25 10:54:53 +0000 (Sun, 25 Oct 2009) | 1 line
  
  Remove insert empty initializer lists, as there's a bug in gcc.
........
  r57152 | danieljames | 2009-10-25 10:55:08 +0000 (Sun, 25 Oct 2009) | 1 line
  
  Slightly rearrange the unordered container headers so that prev_prime is defined before it's used.
........
  r57153 | danieljames | 2009-10-25 10:55:27 +0000 (Sun, 25 Oct 2009) | 1 line
  
  Remove 'grouped' from hash_table as it isn't used and is a bit confusing.
........


[SVN r57179]
2009-10-27 19:39:33 +00:00
Daniel James 2221c8334e Merge a couple of documentation changes.
Merged revisions 56988-56989 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r56988 | danieljames | 2009-10-18 21:18:28 +0100 (Sun, 18 Oct 2009) | 1 line
  
  Add release notes for unordered.
........
  r56989 | danieljames | 2009-10-18 21:18:43 +0100 (Sun, 18 Oct 2009) | 1 line
  
  Mention that image attributes are supported.
........


[SVN r57028]
2009-10-20 23:13:33 +00:00
Daniel James 584eaad67a A couple of bug fixes for unordered containers.
Merged revisions 57005-57006 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r57005 | danieljames | 2009-10-19 20:24:33 +0100 (Mon, 19 Oct 2009) | 6 lines
  
  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.
........
  r57006 | danieljames | 2009-10-19 20:32:09 +0100 (Mon, 19 Oct 2009) | 1 line
  
  Fix allocator for construct from initializer list.
........


[SVN r57027]
2009-10-20 23:05:28 +00:00
Troy D. Straszheim 14e09a5456 rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
Daniel James 06b0b1d31c Merge some documentation changes and inspect fixes.
Merged revisions 55370,55729,56440,56570-56571,56603,56697-56699 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r55370 | danieljames | 2009-08-02 19:18:14 +0100 (Sun, 02 Aug 2009) | 1 line
  
  Pass through more elements in doxygen2boostbook. Refs #3309.
........
  r55729 | danieljames | 2009-08-23 11:07:25 +0100 (Sun, 23 Aug 2009) | 3 lines
  
  Add depencies on doxygen documentation to standalone documentation targets.
  
  This seems to be needed for building pdfs.
........
  r56440 | danieljames | 2009-09-27 20:11:39 +0100 (Sun, 27 Sep 2009) | 1 line
  
  Fix silly error in doxygen test file.
........
  r56570 | danieljames | 2009-10-04 11:37:36 +0100 (Sun, 04 Oct 2009) | 1 line
  
  Clean up some unordered TODOs.
........
  r56571 | danieljames | 2009-10-04 11:37:56 +0100 (Sun, 04 Oct 2009) | 1 line
  
  Detab.
........
  r56603 | danieljames | 2009-10-05 22:29:39 +0100 (Mon, 05 Oct 2009) | 1 line
  
  Various inspect fixes.
........
  r56697 | danieljames | 2009-10-10 14:00:28 +0100 (Sat, 10 Oct 2009) | 1 line
  
  Add forwarding html file for accumulators.
........
  r56698 | danieljames | 2009-10-10 14:01:14 +0100 (Sat, 10 Oct 2009) | 1 line
  
  Missing newline.
........
  r56699 | danieljames | 2009-10-10 14:01:30 +0100 (Sat, 10 Oct 2009) | 1 line
  
  Add copyright to boostbook reference xml.
........


[SVN r56702]
2009-10-10 14:53:46 +00:00
Daniel James 3529bc00dc Merge unordred changes.
Merged revisions 56441,56461,56468,56557-56562 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r56441 | danieljames | 2009-09-27 20:12:04 +0100 (Sun, 27 Sep 2009) | 1 line
  
  Try supporting reference parameters in pairs. Probably not required.
........
  r56461 | danieljames | 2009-09-29 00:06:03 +0100 (Tue, 29 Sep 2009) | 1 line
  
  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.
........
  r56468 | danieljames | 2009-09-29 08:46:44 +0100 (Tue, 29 Sep 2009) | 1 line
  
  Just remove the test since the test itself doesn't work on most compilers.
........
  r56557 | danieljames | 2009-10-03 17:40:26 +0100 (Sat, 03 Oct 2009) | 1 line
  
  Fix the iterator category.
........
  r56558 | danieljames | 2009-10-03 17:40:53 +0100 (Sat, 03 Oct 2009) | 2 lines
  
  Update reference docs to latest version of draft standard and fill in
  some missing details.
........
  r56559 | danieljames | 2009-10-03 17:41:11 +0100 (Sat, 03 Oct 2009) | 1 line
  
  Stricter insert exception tests.
........
  r56560 | danieljames | 2009-10-03 17:41:32 +0100 (Sat, 03 Oct 2009) | 1 line
  
  Insert using initializer lists.
........
  r56561 | danieljames | 2009-10-03 17:42:00 +0100 (Sat, 03 Oct 2009) | 1 line
  
  Update the unordered rationale.
........
  r56562 | danieljames | 2009-10-03 17:42:20 +0100 (Sat, 03 Oct 2009) | 1 line
  
  Make sure inserting from a range of types other than the value type is better tested.
........


[SVN r56700]
2009-10-10 13:52:53 +00:00
Daniel James 1e7fe6a2d0 New version of Boost.Unordered
Merged revisions 55470,55877-55878,55901-55902,55921-55922,55990-55992,56009-56010,56329,56346-56349,56362-56363,56374 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r55470 | danieljames | 2009-08-08 19:50:00 +0100 (Sat, 08 Aug 2009) | 1 line
  
  Remove empty svn:mergeinfo properties. This should reduce the amount of differences between trunk and release.
........
  r55877 | danieljames | 2009-08-30 17:33:42 +0100 (Sun, 30 Aug 2009) | 1 line
  
  Remove allocator_constructor since it's never used.
........
  r55878 | danieljames | 2009-08-30 17:42:28 +0100 (Sun, 30 Aug 2009) | 6 lines
  
  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.
........
  r55901 | danieljames | 2009-08-31 11:39:25 +0100 (Mon, 31 Aug 2009) | 1 line
  
  Detab.
........
  r55902 | danieljames | 2009-08-31 11:39:40 +0100 (Mon, 31 Aug 2009) | 1 line
  
  Remove unnecessary BOOST_DEDUCED_TYPENAMEs
........
  r55921 | danieljames | 2009-08-31 16:33:28 +0100 (Mon, 31 Aug 2009) | 1 line
  
  Remove a few unused parameters.
........
  r55922 | danieljames | 2009-08-31 16:33:49 +0100 (Mon, 31 Aug 2009) | 1 line
  
  Remove 'static' from next_node and node_count. Will hopefully make vacpp happy.
........
  r55990 | danieljames | 2009-09-03 08:36:21 +0100 (Thu, 03 Sep 2009) | 1 line
  
  Combine hash_structure and hash_table_manager.
........
  r55991 | danieljames | 2009-09-03 08:37:14 +0100 (Thu, 03 Sep 2009) | 1 line
  
  Remove some old Visual C++ workarounds.
........
  r55992 | danieljames | 2009-09-03 08:37:30 +0100 (Thu, 03 Sep 2009) | 1 line
  
  Add a small test to see if the tested compilers support out of line template methods.
........
  r56009 | danieljames | 2009-09-04 08:02:28 +0100 (Fri, 04 Sep 2009) | 1 line
  
  Fix link to n2691.
........
  r56010 | danieljames | 2009-09-04 08:03:04 +0100 (Fri, 04 Sep 2009) | 1 line
  
  Move size_ and cached_begin_bucket_ into table, rename hash_table_manager hash_buckets.
........
  r56329 | danieljames | 2009-09-20 22:55:15 +0100 (Sun, 20 Sep 2009) | 2 lines
  
  Since all the compilers support out of line template members use them
  and lots of other things.
........
  r56346 | danieljames | 2009-09-21 22:17:19 +0100 (Mon, 21 Sep 2009) | 1 line
  
  Slightly more consistent variable names. In detail 'n' is now always a node pointer.
........
  r56347 | danieljames | 2009-09-21 22:17:40 +0100 (Mon, 21 Sep 2009) | 1 line
  
  Fix bug where container was reducing the number of buckets.
........
  r56348 | danieljames | 2009-09-21 22:18:01 +0100 (Mon, 21 Sep 2009) | 1 line
  
  Fix a bug that was causing unnecessary rehahes.
........
  r56349 | danieljames | 2009-09-21 22:18:21 +0100 (Mon, 21 Sep 2009) | 1 line
  
  Use std::max.
........
  r56362 | danieljames | 2009-09-22 23:39:00 +0100 (Tue, 22 Sep 2009) | 1 line
  
  Another std::max.
........
  r56363 | danieljames | 2009-09-22 23:39:17 +0100 (Tue, 22 Sep 2009) | 1 line
  
  Remove the emplace_hint implementation for unique containers as it isn't really used and seems to be causing sun 5.7 problems.
........
  r56374 | danieljames | 2009-09-24 21:42:19 +0100 (Thu, 24 Sep 2009) | 1 line
  
  Remove temporary test.
........


[SVN r56375]
2009-09-24 21:12:46 +00:00
Daniel James df1dad5cb6 Merge an unordered documentation change that I missed before.
Merged revisions 54914 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r54914 | danieljames | 2009-07-12 19:03:35 +0100 (Sun, 12 Jul 2009) | 1 line
  
  Add constructors to the methods for controlling bucket size in unordered containers.
........


[SVN r55211]
2009-07-27 20:46:40 +00:00
Daniel James 1bc3ae3d9d Merge unordered changes, including fixes for Boost.TR1.
Merged revisions 55099-55100,55132,55138,55184-55185 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r55099 | danieljames | 2009-07-22 23:37:52 +0100 (Wed, 22 Jul 2009) | 1 line
  
  Fix the insert tests when there is a small number of buckets.
........
  r55100 | danieljames | 2009-07-22 23:38:08 +0100 (Wed, 22 Jul 2009) | 1 line
  
  Adjust the unordered defaults so that emplace takes more parameters and less buckets are created by default.
........
  r55132 | danieljames | 2009-07-23 18:53:59 +0100 (Thu, 23 Jul 2009) | 1 line
  
  Remove the emulation of single argument C++0x std::pair constructor.
........
  r55138 | danieljames | 2009-07-23 23:17:20 +0100 (Thu, 23 Jul 2009) | 1 line
  
  Try to work around an odd Visual C++ 8 bug.
........
  r55184 | danieljames | 2009-07-26 19:59:33 +0100 (Sun, 26 Jul 2009) | 1 line
  
  Some extra changelog notes.
........
  r55185 | danieljames | 2009-07-26 20:00:40 +0100 (Sun, 26 Jul 2009) | 1 line
  
  Update the reference documentation to mention that emplace is now emulated.
........


[SVN r55189]
2009-07-26 20:22:48 +00:00
Troy D. Straszheim 60ecf12779 Add basic copyright/license to keep cmake out of the inspection report
[SVN r55095]
2009-07-22 21:51:01 +00:00
Daniel James 241316e0d9 Misc. unordered changes. Fixes #3082, #3119.
Merged revisions 53505-53506,53525,53550,53552,53614 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r53505 | danieljames | 2009-05-31 16:50:56 +0100 (Sun, 31 May 2009) | 1 line
  
  Disable incorrect Visual C++ 64-bit warnings. Ref #3082.
........
  r53506 | danieljames | 2009-05-31 16:53:09 +0100 (Sun, 31 May 2009) | 1 line
  
  Remove misplaced visual C++ warning pragma.
........
  r53525 | danieljames | 2009-06-01 07:50:37 +0100 (Mon, 01 Jun 2009) | 1 line
  
  Fix tests for when the library has support for initializer lists but the compiler doesn't.
........
  r53550 | danieljames | 2009-06-01 20:17:49 +0100 (Mon, 01 Jun 2009) | 1 line
  
  Get the type of the initializer_list right.
........
  r53552 | danieljames | 2009-06-01 20:22:27 +0100 (Mon, 01 Jun 2009) | 1 line
  
  Fix the unordered_map declaration in the tutorial. Fixes #3119.
........
  r53614 | danieljames | 2009-06-03 23:48:49 +0100 (Wed, 03 Jun 2009) | 1 line
  
  The move tests pass on 64 bit visual c++.
........


[SVN r53687]
2009-06-06 14:05:54 +00:00
Daniel James 9c43533655 A couple more minor unordered changes.
Merged revisions 53312,53367 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r53312 | danieljames | 2009-05-27 18:43:22 +0100 (Wed, 27 May 2009) | 1 line
  
  Remove obsolete comment.
........
  r53367 | danieljames | 2009-05-28 23:06:42 +0100 (Thu, 28 May 2009) | 1 line
  
  Remove a couple of old uses of BOOST_NO_INITIALIZER_LISTS.
........


[SVN r53466]
2009-05-30 17:41:05 +00:00
Daniel James ae09b0dd24 Merge latest changes for unordered. Improved compatability and a few tweaks.
Merged revisions 53127,53253,53256,53311,53314,53316-53318 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r53127 | danieljames | 2009-05-20 07:43:38 +0100 (Wed, 20 May 2009) | 1 line
  
  Better configuration for boost.unordered.
........
  r53253 | danieljames | 2009-05-25 20:14:07 +0100 (Mon, 25 May 2009) | 3 lines
  
  Add explicit destructors to the unordered containers. Refs #2908.
  
  Isn't really needed but it doesn't hurt.
........
  r53256 | danieljames | 2009-05-25 20:45:23 +0100 (Mon, 25 May 2009) | 1 line
  
  Unordered change log for explicit destructors.
........
  r53311 | danieljames | 2009-05-27 18:42:01 +0100 (Wed, 27 May 2009) | 1 line
  
  Missing changelog entry.
........
  r53314 | danieljames | 2009-05-27 18:44:09 +0100 (Wed, 27 May 2009) | 1 line
  
  Use lightweight_test for unordered.
........
  r53316 | danieljames | 2009-05-27 19:19:32 +0100 (Wed, 27 May 2009) | 1 line
  
  Some workarounds for old versions of Borland.
........
  r53317 | danieljames | 2009-05-27 19:32:22 +0100 (Wed, 27 May 2009) | 1 line
  
  Fix a change accidentally included in the last commit.
........
  r53318 | danieljames | 2009-05-27 19:32:38 +0100 (Wed, 27 May 2009) | 1 line
  
  Remove an unused function.
........


[SVN r53465]
2009-05-30 17:34:12 +00:00
Daniel James b018f8b173 Second try at merging emplace support.
Note that the previously rolled back commit was [53257], not [52357].

Merged revisions 52393-52394,52397,52884-52885,53255 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r52393 | danieljames | 2009-04-14 18:23:37 +0100 (Tue, 14 Apr 2009) | 2 lines
  
  Implement full extract_key for compilers without SFINAE and variadic
  templates.
........
  r52394 | danieljames | 2009-04-14 18:23:51 +0100 (Tue, 14 Apr 2009) | 1 line
  
  Use emplace instead of insert in the backend as it's more appropriate.
........
  r52397 | danieljames | 2009-04-14 18:51:34 +0100 (Tue, 14 Apr 2009) | 1 line
  
  Add stream output to the count test helper for unordered.
........
  r52884 | danieljames | 2009-05-10 22:24:41 +0100 (Sun, 10 May 2009) | 19 lines
  
  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.
  ------------------------------------------------------------------------
........
  r52885 | danieljames | 2009-05-10 22:25:09 +0100 (Sun, 10 May 2009) | 1 line
  
  Merge emplace support for sandbox - but without move support.
........
  r53255 | danieljames | 2009-05-25 20:45:06 +0100 (Mon, 25 May 2009) | 1 line
  
  Unordered change log.
........


[SVN r53328]
2009-05-27 21:31:08 +00:00
Daniel James 0b4241833d Rollback [52357] as it depends on macros that aren't in release.
Rolled back revisions 52393-52394,52397,52884-52885,53127,53255 via svnmerge from 
https://svn.boost.org/svn/boost/trunk


[SVN r53277]
2009-05-26 09:56:59 +00:00
Daniel James e911a8011b Merge unordered changes:
* Support emplace for all compilers.
 * Better configuration of C++0x features for when the appropriate headers
   aren't available.

Merged revisions 52393-52394,52397,52884-52885,53127,53255 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r52393 | danieljames | 2009-04-14 18:23:37 +0100 (Tue, 14 Apr 2009) | 2 lines
  
  Implement full extract_key for compilers without SFINAE and variadic
  templates.
........
  r52394 | danieljames | 2009-04-14 18:23:51 +0100 (Tue, 14 Apr 2009) | 1 line
  
  Use emplace instead of insert in the backend as it's more appropriate.
........
  r52397 | danieljames | 2009-04-14 18:51:34 +0100 (Tue, 14 Apr 2009) | 1 line
  
  Add stream output to the count test helper for unordered.
........
  r52884 | danieljames | 2009-05-10 22:24:41 +0100 (Sun, 10 May 2009) | 19 lines
  
  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.
  ------------------------------------------------------------------------
........
  r52885 | danieljames | 2009-05-10 22:25:09 +0100 (Sun, 10 May 2009) | 1 line
  
  Merge emplace support for sandbox - but without move support.
........
  r53127 | danieljames | 2009-05-20 07:43:38 +0100 (Wed, 20 May 2009) | 1 line
  
  Better configuration for boost.unordered.
........
  r53255 | danieljames | 2009-05-25 20:45:06 +0100 (Mon, 25 May 2009) | 1 line
  
  Unordered change log.
........


[SVN r53257]
2009-05-25 19:57:04 +00:00
Daniel James f02cc7775d Long term fix for the incorrect length of prime list.
Merged revisions 52658,52669,52673,52711 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r52658 | danieljames | 2009-04-29 11:05:17 +0100 (Wed, 29 Apr 2009) | 1 line
  
  Fix the length of the prime number list.
........
  r52669 | danieljames | 2009-04-29 22:43:41 +0100 (Wed, 29 Apr 2009) | 3 lines
  
  Don't test prime_list::length on Visual C++.
  
  Checking the array size doesn't seem to work on it.
........
  r52673 | danieljames | 2009-04-30 06:08:40 +0100 (Thu, 30 Apr 2009) | 1 line
  
  Revert changes to unordered, as the test fails on most compilers.
........
  r52711 | danieljames | 2009-05-01 21:50:32 +0100 (Fri, 01 May 2009) | 5 lines
  
  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 r53043]
2009-05-16 13:38:37 +00:00
Troy D. Straszheim 4e6b5de196 tuning up cmakefiles for unordered, utility
[SVN r53008]
2009-05-15 00:21:14 +00:00
Daniel James fb71e0618d Last minute merge, remove google analytics script tags and fixes #2975.
Merged revisions 52665,52674 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r52665 | danieljames | 2009-04-29 22:16:10 +0100 (Wed, 29 Apr 2009) | 1 line
  
  Remove google analytics script tags.
........
  r52674 | danieljames | 2009-04-30 06:10:57 +0100 (Thu, 30 Apr 2009) | 1 line
  
  Fix the prime number list length in unordered.
........


[SVN r52707]
2009-05-01 19:00:57 +00:00
Daniel James 694398f0e1 Some small documentation fixes for the release.
Merged revisions 52348-52350 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r52348 | danieljames | 2009-04-12 11:50:31 +0100 (Sun, 12 Apr 2009) | 1 line
  
  Use a test file that's actually valid C++.
........
  r52349 | danieljames | 2009-04-12 11:50:43 +0100 (Sun, 12 Apr 2009) | 3 lines
  
  Revert support for static mutable variables.
  
  Of course there's no such thing.
........
  r52350 | danieljames | 2009-04-12 11:50:57 +0100 (Sun, 12 Apr 2009) | 1 line
  
  Note change to operator[] in the unordered release notes.
........


[SVN r52351]
2009-04-12 10:54:44 +00:00
Daniel James ab62d33495 Merged revisions 52224 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r52224 | danieljames | 2009-04-06 23:51:36 +0100 (Mon, 06 Apr 2009) | 1 line
  
  Avoid an unnecessary copy in 'operator[]'
........


[SVN r52346]
2009-04-12 10:25:38 +00:00
Daniel James b475ba05c0 Merge quickbook and hash changelogs. Tweak gcc detection in container_fwd.hpp
Merged revisions 52084,52245-52246,52304,52320,52323 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r52084 | danieljames | 2009-03-31 20:43:58 +0100 (Tue, 31 Mar 2009) | 1 line
  
  Changelog for unordered and hash.
........
  r52245 | danieljames | 2009-04-08 06:51:31 +0100 (Wed, 08 Apr 2009) | 5 lines
  
  Detect gcc stdlib for gcc 4.0.1.
  
  For some reason the normal macros aren't defined for the standard
  library that comes with gcc 4.0.1 (although maybe just on BSDs?). So try
  to detect the library for that compiler.
........
  r52246 | danieljames | 2009-04-08 11:56:22 +0100 (Wed, 08 Apr 2009) | 7 lines
  
  Include <utility> for some versions of gcc's library.
  
  Sometimes gcc's <cstddef> doesn't define the C++ macros, so check for it
  and include <utility> in that case. Also remove a workaround from
  container_fwd.hpp
  
  Fixes #2924.
........
  r52304 | danieljames | 2009-04-10 20:25:32 +0100 (Fri, 10 Apr 2009) | 4 lines
  
  Don't use debug containers on darwin.
  
  I'm getting errors from the darwin 4.2 debug containers which appear to
  a problem with its implementation.
........
  r52320 | danieljames | 2009-04-11 08:53:59 +0100 (Sat, 11 Apr 2009) | 1 line
  
  Don't need to include utility now that select_stdlib has been fixed.
........
  r52323 | danieljames | 2009-04-11 09:26:20 +0100 (Sat, 11 Apr 2009) | 1 line
  
  Also don't need to check for _GLIBCXX_CSTDDEF.
........


[SVN r52324]
2009-04-11 08:49:33 +00:00
Daniel James 60e3e96b48 Tweak unordered for some compilers.
Fixes #2756.

Merged revisions 51982-51983,51995 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r51982 | danieljames | 2009-03-26 07:00:21 +0000 (Thu, 26 Mar 2009) | 3 lines
  
  Revert [51409]
  
  It isn't working on Borland.
........
  r51983 | danieljames | 2009-03-26 07:00:46 +0000 (Thu, 26 Mar 2009) | 1 line
  
  Try to destruct values in a way that all compilers might like.
........
  r51995 | danieljames | 2009-03-26 21:09:51 +0000 (Thu, 26 Mar 2009) | 1 line
  
  Give up and use another macro to destruct values.
........


[SVN r52065]
2009-03-30 17:54:49 +00:00
Daniel James c0e472755e Merge misc. changes from trunk, mostly minor documentation fixes.
Merged revisions 48412,50921,51042,51369,51386-51387,51506-51507,51668,51802,51804,51881 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r48412 | danieljames | 2008-08-28 11:23:33 +0100 (Thu, 28 Aug 2008) | 1 line
  
  Fix a typo. Thanks to Jon Biggar.
........
  r50921 | danieljames | 2009-01-31 09:36:38 +0000 (Sat, 31 Jan 2009) | 1 line
  
  Remove executable flag from preprocess.cmd. It was a mistake to add it.
........
  r51042 | danieljames | 2009-02-06 00:04:44 +0000 (Fri, 06 Feb 2009) | 1 line
  
  Ignore some version control files in inspect.
........
  r51369 | danieljames | 2009-02-21 18:49:48 +0000 (Sat, 21 Feb 2009) | 1 line
  
  Minor markup fix in concept check documentation.
........
  r51386 | danieljames | 2009-02-22 11:53:28 +0000 (Sun, 22 Feb 2009) | 1 line
  
  Add index.html file for compose, as our server setup doesn't support index.htm files.
........
  r51387 | danieljames | 2009-02-22 11:53:48 +0000 (Sun, 22 Feb 2009) | 5 lines
  
  Add missing index.html file for MPI and GIL.
  
  All the top level libraries now have index.html files but
  several sub-libraries don't. I'm not sure it's worth adding them as many
  of them don't have appropriate subdirectories anyway.
........
  r51506 | danieljames | 2009-03-01 14:16:00 +0000 (Sun, 01 Mar 2009) | 1 line
  
  Update links to command line invocation.
........
  r51507 | danieljames | 2009-03-01 14:16:24 +0000 (Sun, 01 Mar 2009) | 1 line
  
  Use xpointer attributes in the boost build documentation.
........
  r51668 | danieljames | 2009-03-09 20:56:51 +0000 (Mon, 09 Mar 2009) | 1 line
  
  Redirect to the Trac wiki instead of the old one.
........
  r51802 | danieljames | 2009-03-16 20:21:05 +0000 (Mon, 16 Mar 2009) | 1 line
  
  Use paragraphs inside purpose tags.
........
  r51804 | danieljames | 2009-03-16 20:21:46 +0000 (Mon, 16 Mar 2009) | 1 line
  
  Give the variablelist a margin.
........
  r51881 | danieljames | 2009-03-21 15:35:35 +0000 (Sat, 21 Mar 2009) | 1 line
  
  Fix html.
........


[SVN r51897]
2009-03-22 10:42:48 +00:00
Daniel James 6f45d36d97 Merge hash and unordered changes.
Remove deprecated headers, move hash_fwd.hpp into hash subdirectory. And
several minor internal changes.
Mostly minor internal details.

Merged revisions 51262-51263,51407-51409,51504-51505,51644-51646,51667 via svnmerge from 
https://svn.boost.org/svn/boost/trunk

........
  r51262 | danieljames | 2009-02-15 19:32:04 +0000 (Sun, 15 Feb 2009) | 1 line
  
  Use the new 'boost:' links for the hash, unordered and quickbook documentation.
........
  r51263 | danieljames | 2009-02-15 19:32:19 +0000 (Sun, 15 Feb 2009) | 2 lines
  
  Don't copy images for the standalone hash and unordered documentation, was only
  really required before the libraries were integrated into boost.
........
  r51407 | danieljames | 2009-02-22 23:49:51 +0000 (Sun, 22 Feb 2009) | 1 line
  
  Fix the hash dirname.
........
  r51408 | danieljames | 2009-02-22 23:50:04 +0000 (Sun, 22 Feb 2009) | 1 line
  
  Make copy_buckets and move_buckets member functions - so that calling them is a bit simpler.
........
  r51409 | danieljames | 2009-02-22 23:50:20 +0000 (Sun, 22 Feb 2009) | 1 line
  
  Move some of the data structure classes out of hash table data.
........
  r51504 | danieljames | 2009-03-01 14:15:09 +0000 (Sun, 01 Mar 2009) | 1 line
  
  Add missing return for operator=.
........
  r51505 | danieljames | 2009-03-01 14:15:39 +0000 (Sun, 01 Mar 2009) | 3 lines
  
  Make the sort stable.
  
  Doesn't really matter, but it might as well be.
........
  r51644 | danieljames | 2009-03-08 09:44:51 +0000 (Sun, 08 Mar 2009) | 1 line
  
  Detab.
........
  r51645 | danieljames | 2009-03-08 09:45:11 +0000 (Sun, 08 Mar 2009) | 4 lines
  
  Move hash_fwd into the hash subdirectory.
  
  I should have done this in the last release. But now all of the hash
  implementation is in the hash subdirectory.
........
  r51646 | danieljames | 2009-03-08 09:45:30 +0000 (Sun, 08 Mar 2009) | 3 lines
  
  Remove deprecated headers.
  
  Fixes #2412.
........
  r51667 | danieljames | 2009-03-09 20:56:23 +0000 (Mon, 09 Mar 2009) | 1 line
  
  Update copyright dates in hash and unordered.
........


[SVN r51729]
2009-03-11 22:51:09 +00:00
John Maddock 2e9cf20cd0 Merge PDF build changes from Trunk.
[SVN r51417]
2009-02-23 18:39:32 +00:00
94 changed files with 7492 additions and 4652 deletions
-23
View File
@@ -1,23 +0,0 @@
#----------------------------------------------------------------------------
# This file was automatically generated from the original CMakeLists.txt file
# Add a variable to hold the headers for the library
set (lib_headers
unordered_map.hpp
unordered_set.hpp
unordered
)
# Add a library target to the build system
boost_library_project(
unordered
# SRCDIRS
# TESTDIRS
HEADERS ${lib_headers}
# DOCDIRS
# DESCRIPTION
MODULARIZED
# AUTHORS
# MAINTAINERS
)
+8 -13
View File
@@ -8,11 +8,6 @@ path-constant admonishment_location : ../../../../doc/src/images ;
xml unordered : unordered.qbk ;
boostbook standalone : unordered :
<xsl:param>admon.graphics.path=images/
<xsl:param>navig.graphics.path=images/
<xsl:param>html.stylesheet=boostbook.css
<xsl:param>boost.root=../../../..
<xsl:param>boost.libraries=../../../libraries.htm
<xsl:param>chunk.first.sections=1
<xsl:param>chunk.section.depth=2
<xsl:param>generate.section.toc.level=2
@@ -23,10 +18,15 @@ boostbook standalone : unordered :
<xsl:param>boost.compact.function=0
<xsl:param>boost.compact.enum=0
<dependency>css
<dependency>images
# HTML Options:
<format>html:<xsl:param>boost.root=../../../..
<format>html:<xsl:param>img.src.path=../../../../doc/html/
<format>xhtml:<xsl:param>boost.root=../../../..
<format>xhtml:<xsl:param>img.src.path=../../../../doc/html/
# PDF Options:
# TOC Generation: this is needed for FOP-0.9 and later:
<xsl:param>fop1.extensions=0
<format>pdf:<xsl:param>xep.extensions=1
@@ -51,11 +51,6 @@ boostbook standalone : unordered :
<format>pdf:<xsl:param>img.src.path=$(images_location)/
#<format>pdf:<xsl:param>admon.graphics.path=$(admonishment_location)
<format>pdf:<xsl:param>draft.mode="no"
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/unordered/doc/html
;
install css : [ glob $(BOOST_ROOT)/doc/src/*.css ]
: <location>html ;
install images : [ glob $(BOOST_ROOT)/doc/src/images/*.png ]
: <location>html/images ;
explicit css ;
explicit images ;
+1 -1
View File
@@ -1,5 +1,5 @@
<!--
Copyright Daniel James 2008
Copyright Daniel James 2008-2009
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)
-->
+9
View File
@@ -115,6 +115,15 @@ or close to the hint - unless your hint is unreasonably small or large.
[table Methods for Controlling Bucket Size
[[Method] [Description]]
[
[`X(size_type n)`]
[Construct an empty container with at least `n` buckets (`X` is the container type).]
]
[
[`X(InputIterator i, InputIterator j, size_type n)`]
[Construct an empty container with at least `n` buckets and insert elements
from the range \[`i`, `j`) (`X` is the container type).]
]
[
[`float load_factor() const`]
[The average number of elements per bucket.]
+74 -2
View File
@@ -44,7 +44,7 @@ First official release.
[h2 Boost 1.38.0]
* Use [@../../libs/utility/swap.html `boost::swap`].
* Use [@boost:/libs/utility/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
@@ -53,7 +53,7 @@ First official release.
Use a larger prime number list. Thanks to Thorsten Ottosen and Hervé
Brönnimann.
* Use
[@../../libs/type_traits/doc/html/boost_typetraits/category/alignment.html
[@boost:/libs/type_traits/doc/html/boost_typetraits/category/alignment.html
aligned storage] to store the types. This changes the way the allocator is
used to construct nodes. It used to construct the node with two calls to
the allocator's `construct` method - once for the pointers and once for the
@@ -62,4 +62,76 @@ First official release.
* Add support for C++0x initializer lists where they're available (currently
only g++ 4.4 in C++0x mode).
[h2 Boost 1.39.0]
* [@https://svn.boost.org/trac/boost/ticket/2756 Ticket 2756]: Avoid a warning
on Visual C++ 2009.
* Some other minor internal changes to the implementation, tests and
documentation.
* Avoid an unnecessary copy in `operator[]`.
* [@https://svn.boost.org/trac/boost/ticket/2975 Ticket 2975]: Fix length of
prime number list.
[h2 Boost 1.40.0]
* [@https://svn.boost.org/trac/boost/ticket/2975 Ticket 2975]:
Store the prime list as a preprocessor sequence - so that it will always get
the length right if it changes again in the future.
* [@https://svn.boost.org/trac/boost/ticket/1978 Ticket 1978]:
Implement `emplace` for all compilers.
* [@https://svn.boost.org/trac/boost/ticket/2908 Ticket 2908],
[@https://svn.boost.org/trac/boost/ticket/3096 Ticket 3096]:
Some workarounds for old versions of borland, including adding explicit
destructors to all containers.
* [@https://svn.boost.org/trac/boost/ticket/3082 Ticket 3082]:
Disable incorrect Visual C++ warnings.
* Better configuration for C++0x features when the headers aren't available.
* Create less buckets by default.
[h2 Boost 1.41.0 - Major update]
* The original version made heavy use of macros to sidestep some of the older
compilers' poor template support. But since I no longer support those
compilers and the macro use was starting to become a maintenance burden it
has been rewritten to use templates instead of macros for the implementation
classes.
* The container objcet is now smaller thanks to using `boost::compressed_pair`
for EBO and a slightly different function buffer - now using a bool instead
of a member pointer.
* Buckets are allocated lazily which means that constructing an empty container
will not allocate any memory.
[h2 Boost 1.42.0]
* Support instantiating the containers with incomplete value types.
* Reduced the number of warnings (mostly in tests).
* Improved codegear compatibility.
* [@http://svn.boost.org/trac/boost/ticket/3693 Ticket 3693]:
Add `erase_return_void` as a temporary workaround for the current
`erase` which can be inefficient because it has to find the next
element to return an iterator.
* Add templated find overload for compatible keys.
* [@http://svn.boost.org/trac/boost/ticket/3773 Ticket 3773]:
Add missing `std` qualifier to `ptrdiff_t`.
* Some code formatting changes to fit almost all lines into 80 characters.
[h2 Boost 1.43.0]
* [@http://svn.boost.org/trac/boost/ticket/3966 Ticket 3966]:
`erase_return_void` is now `quick_erase`, which is the
[@http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#579
current forerunner for resolving the slow erase by iterator], although
there's a strong possibility that this may change in the future. The old
method name remains for backwards compatibility but is considered deprecated
and will be removed in a future release.
* Use Boost.Exception.
* Stop using deprecated `BOOST_HAS_*` macros.
[h2 Boost 1.45.0]
* Fix a bug when inserting into an `unordered_map` or `unordered_set` using
iterators which returns `value_type` by copy.
[endsect]
+3 -3
View File
@@ -13,7 +13,7 @@ is declared as:
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]``;
The hash function comes first as you might want to change the hash function
@@ -23,7 +23,7 @@ but not the equality predicate. For example, if you wanted to use the
[import src_code/dictionary.cpp]
[case_sensitive_dictionary_fnv]
There is an [@../../libs/unordered/examples/fnv1.hpp implementation
There is an [@boost:/libs/unordered/examples/fnv1.hpp implementation
of FNV-1] in the examples directory.
If you wish to use a different equality function,
@@ -38,7 +38,7 @@ Which you can then use in a case insensitive dictionary:
[case_insensitive_dictionary]
This is a simplified version of the example at
[@../../libs/unordered/examples/case_insensitive.hpp /libs/unordered/examples/case_insensitive.hpp]
[@boost:/libs/unordered/examples/case_insensitive.hpp /libs/unordered/examples/case_insensitive.hpp]
which supports other locales and string types.
[caution
+1 -1
View File
@@ -9,7 +9,7 @@
[@http://www.boost.org/doc/html/boost_tr1.html
Boost.TR1]]
[def __draft__
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2691.pdf
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2960.pdf
Working Draft of the C++ Standard]]
[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table
hash table]]
+30 -92
View File
@@ -5,12 +5,6 @@
[def __wang__
[@http://www.concentric.net/~Ttwang/tech/inthash.htm
Thomas Wang's article on integer hash functions]]
[def __n2345__
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2345.pdf
N2345, 'Placement Insert for Containers']]
[def __n2369__
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2369.pdf
the August 2007 version of the working draft standard]]
[section:rationale Implementation Rationale]
@@ -99,105 +93,49 @@ So, this implementation uses a prime number for the hash table size.
[h2 Equality operators]
`operator==` and `operator!=` are not included in the standard, but I've
added them as I think they could be useful and can be efficiently
implemented. They are specified
differently to the standard associative containers, comparing keys
using the equality predicate rather than `operator==`. This is inconsistent
with the other containers but it is probably closer to user's expectations.
added them as I think they could be useful and can be implemented
fairly efficiently. They are specified differently to the other standard
containers, comparing keys using the equality predicate rather than
`operator==`.
It's also different to the proposal
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2944.pdf n2944].
which uses the equality operators for the whole of `value_type`. This
implementation just uses the key equality function for the key,
and `mapped_type`'s equality operator in `unordered_map` and
`unordered_multimap` for the mapped part of the element.
Also, in `unordered_multimap`, the mapped values for a group of elements with
equivalent keys are only considered equal if they are in the same order,
in n2944 they just need to be a permutation of each other. Since the
order of elements with equal keys is now defined to be stable, it seems to me
that their order can be considered part of the container's value.
[h2 Active Issues and Proposals]
[h3 Removing unused allocator functions]
[h3 C++0x allocators]
In
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2257.html
N2257, removing unused allocator functions],
Matt Austern suggests removing the `construct`, `destroy` and `address` member
functions - all of which Boost.Unordered calls. Changing this will simplify the
implementation, as well as make supporting `emplace` easier, but means that the
containers won't support allocators which require these methods to be called.
Detlef Vollmann opposed this change in
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2339.htm N2339].
Recent drafts have included an overhaul of the allocators, but this was
dependent on concepts which are no longer in the standard.
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2946.pdf n2946]
attempts to respecify them without concepts. I'll try to implement this (or
an appropriate later version) in a future version of boost, possibly changed
a little to accomodate non-C++0x compilers.
[h3 Swapping containers with unequal allocators]
It isn't clear how to swap containers when their allocators aren't equal.
This is
[@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#431
Issue 431: Swapping containers with unequal allocators].
Howard Hinnant wrote about this in
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1599.html N1599]
and suggested swapping both the allocators and the containers' contents.
But the committee have now decided that `swap` should do a fast swap if the
allocator is Swappable and a slow swap using copy construction otherwise. To
make this distinction requires concepts.
In
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2387.pdf
N2387, Omnibus Allocator Fix-up Proposals],
Pablo Halpern suggests that there are actually two distinct allocator models,
"Moves with Value" and "Scoped" which behave differently:
[:
When allocators are allowed to have state, it is necessary to have a model for
determining from where an object obtains its allocator. Weve identified two such
models: the “Moves with Value” allocator model and the “Scoped” allocator model.
In the “Moves with Value” allocator model, the copy constructor of an allocator-aware
class will copy both the value and the allocator from its argument. This is the model
specified in the C++03 standard. With this model, inserting an object into a container
usually causes the new container item to copy the allocator from the object that was
inserted. This model can be useful in special circumstances, e.g., if the items within a
container use an allocator that is specially tuned to the items type.
In the “Scoped” allocator model, the allocator used to construct an object is determined
by the context of that object, much like a storage class. With this model, inserting an
object into a container causes the new container item to use the same allocator as the
container. To avoid allocators being used in the wrong context, the allocator is never
copied during copy or move construction. Thus, it is possible using this model to use
allocators based on short-lived resources without fear that an object will transfer its
allocator to a copy that might outlive the (shared) allocator resource. This model is
reasonably safe and generally useful on a large scale. There was strong support in the
2005 Tremblant meeting for pursuing an allocator model that propagates allocators
from container to contained objects.
]
With these models the choice becomes clearer:
[:
I introduced the “Moves with Value” allocator model and the
“Scoped” allocator model. In the former case, the allocator is copied when the container
is copy-constructed. In the latter case it is not. Swapping the allocators is the right thing
to do if the containers conform to the “Moves with Value” allocator model and
absolutely the wrong thing to do if the containers conform to the “Scoped” allocator
model. With the two allocator models well-defined, the desired behavior becomes clear.
]
The proposal is that allocators are swapped if the allocator follows the
"Moves with Value" model and the allocator is swappable. Otherwise a slow swap
is used. Since containers currently only support the "Moves with Value" model
this is consistent with the committee's current recommendation (although it
suggests using a trait to detect if the allocator is swappable rather than a
concept).
Since there is currently neither have a swappable trait or concept for
allocators this implementation always performs a slow swap.
Issue 431: Swapping containers with unequal allocators]. This has been resolved
with the new allocator specification, so this should be fixed when
support is added.
[h3 Are insert and erase stable for unordered_multiset and unordered_multimap?]
It is not specified if `unordered_multiset` and `unordered_multimap` preserve the order
It wan't specified if `unordered_multiset` and `unordered_multimap` preserve the order
of elements with equivalent keys (i.e. if they're stable under `insert` and `erase`).
This is [@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#518 issue 581].
The current proposal is that insert, erase and rehash are stable - so they are here.
(Update: during the release of this version, this requirement was added to
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2691.pdf
the lastest working draft]).
[h3 const_local_iterator cbegin, cend missing from TR1]
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2684.html#691
Issue 691] is that `cbegin` and `cend` are missing for local iterators.
The current resolution is that they'll be added, so I've added them.
Since [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2691.pdf
n2691] it's been specified that they do and this implementation follows that.
[endsect]
+661 -41
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
+1 -1
View File
@@ -13,7 +13,7 @@
[license
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]
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
+7 -4
View File
@@ -1,5 +1,5 @@
// Copyright 2008 Daniel James.
// 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)
@@ -55,11 +55,14 @@ namespace hash
// For 128 bit machines:
// const std::size_t fnv_prime = 309485009821345068724781401u;
// const std::size_t fnv_offset_basis = 275519064689413815358837431229664493455u;
// const std::size_t fnv_offset_basis =
// 275519064689413815358837431229664493455u;
// For 256 bit machines:
// const std::size_t fnv_prime = 374144419156711147060143317175368453031918731002211u;
// const std::size_t fnv_offset_basis = 100029257958052580907070968620625704837092796014241193945225284501741471925557u;
// const std::size_t fnv_prime =
// 374144419156711147060143317175368453031918731002211u;
// const std::size_t fnv_offset_basis =
// 100029257958052580907070968620625704837092796014241193945225284501741471925557u;
typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;
typedef basic_fnv_1a<fnv_prime, fnv_offset_basis> fnv_1a;
@@ -1,8 +1,10 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-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)
// A couple of templates to make using allocators easier.
#ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED
@@ -21,214 +23,86 @@
# include <boost/detail/allocator_utilities.hpp>
#endif
#include <boost/mpl/aux_/config/eti.hpp>
namespace boost { namespace unordered_detail {
namespace boost {
namespace unordered_detail {
// rebind_wrap
//
// Rebind allocators. For some problematic libraries, use rebind_to
// from <boost/detail/allocator_utilities.hpp>.
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
template <class Alloc, class T>
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
template <class Alloc, class T>
struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {};
#else
template <class Alloc, class T>
struct rebind_wrap
{
typedef BOOST_DEDUCED_TYPENAME
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type;
};
template <class Alloc, class T>
struct rebind_wrap
{
typedef BOOST_DEDUCED_TYPENAME
Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other
type;
};
#endif
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T>
inline void reset(T& x) { x = T(); }
// allocator_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 <class Ptr>
inline Ptr null_ptr() { return Ptr(); }
#else
template <class T>
inline void reset_impl(T& x, ...) { x = T(); }
template <class T>
inline void reset_impl(T*& x, int) { x = 0; }
template <class T>
inline void reset(T& x) { reset_impl(x); }
template <class Allocator>
struct allocator_array_constructor
{
typedef BOOST_DEDUCED_TYPENAME Allocator::pointer pointer;
template <class Ptr>
inline Ptr null_ptr() { Ptr x; reset(x); return x; }
#endif
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
// Work around for Microsoft's ETI bug.
template <class Allocator> struct allocator_value_type
allocator_array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
{
typedef BOOST_DEDUCED_TYPENAME Allocator::value_type type;
};
constructed_ = pointer();
ptr_ = pointer();
}
template <class Allocator> struct allocator_pointer
{
typedef BOOST_DEDUCED_TYPENAME Allocator::pointer type;
};
template <class Allocator> struct allocator_const_pointer
{
typedef BOOST_DEDUCED_TYPENAME Allocator::const_pointer type;
};
template <class Allocator> struct allocator_reference
{
typedef BOOST_DEDUCED_TYPENAME Allocator::reference type;
};
template <class Allocator> struct allocator_const_reference
{
typedef BOOST_DEDUCED_TYPENAME Allocator::const_reference type;
};
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
~allocator_array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
alloc_.destroy(p);
template <>
struct allocator_value_type<int>
{
typedef int type;
};
template <>
struct allocator_pointer<int>
{
typedef int type;
};
template <>
struct allocator_const_pointer<int>
{
typedef int type;
};
template <>
struct allocator_reference<int>
{
typedef int type;
};
template <>
struct allocator_const_reference<int>
{
typedef int type;
};
#endif
template <class Allocator>
struct allocator_constructor
{
typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Allocator>::type value_type;
typedef BOOST_DEDUCED_TYPENAME allocator_pointer<Allocator>::type pointer;
Allocator& alloc_;
pointer ptr_;
bool constructed_;
allocator_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(false)
{
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
unordered_detail::reset(ptr_);
#endif
alloc_.deallocate(ptr_, length_);
}
}
~allocator_constructor() {
if(ptr_) {
if(constructed_) alloc_.destroy(ptr_);
alloc_.deallocate(ptr_, 1);
}
}
template <class V>
void construct(V const& v) {
BOOST_ASSERT(!ptr_ && !constructed_);
ptr_ = alloc_.allocate(1);
alloc_.construct(ptr_, value_type(v));
constructed_ = true;
}
void construct(value_type const& v) {
BOOST_ASSERT(!ptr_ && !constructed_);
ptr_ = alloc_.allocate(1);
alloc_.construct(ptr_, v);
constructed_ = true;
}
pointer get() const
{
return ptr_;
}
// no throw
pointer release()
{
pointer p = ptr_;
constructed_ = false;
unordered_detail::reset(ptr_);
return p;
}
};
template <class Allocator>
struct allocator_array_constructor
template <class V>
void construct(V const& v, std::size_t l)
{
typedef BOOST_DEDUCED_TYPENAME allocator_pointer<Allocator>::type pointer;
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = alloc_.allocate(length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
alloc_.construct(constructed_, v);
}
Allocator& alloc_;
pointer ptr_;
pointer constructed_;
std::size_t length_;
pointer get() const
{
return ptr_;
}
allocator_array_constructor(Allocator& a)
: alloc_(a), ptr_(), constructed_(), length_(0)
{
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
unordered_detail::reset(constructed_);
unordered_detail::reset(ptr_);
#endif
}
~allocator_array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p)
alloc_.destroy(p);
alloc_.deallocate(ptr_, length_);
}
}
template <class V>
void construct(V const& v, std::size_t l)
{
BOOST_ASSERT(!ptr_);
length_ = l;
ptr_ = alloc_.allocate(length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
alloc_.construct(constructed_, v);
}
pointer get() const
{
return ptr_;
}
pointer release()
{
pointer p(ptr_);
unordered_detail::reset(ptr_);
return p;
}
private:
allocator_array_constructor(allocator_array_constructor const&);
allocator_array_constructor& operator=(allocator_array_constructor const&);
};
}
}
pointer release()
{
pointer p(ptr_);
ptr_ = pointer();
return p;
}
private:
allocator_array_constructor(allocator_array_constructor const&);
allocator_array_constructor& operator=(
allocator_array_constructor const&);
};
}}
#if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES)
# undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES
+183
View File
@@ -0,0 +1,183 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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)
#ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/unordered/detail/node.hpp>
#include <boost/unordered/detail/util.hpp>
namespace boost { namespace unordered_detail {
////////////////////////////////////////////////////////////////////////////
// Buckets
template <class A, class G>
inline std::size_t hash_buckets<A, G>::max_bucket_count() const {
// -1 to account for the sentinel.
return prev_prime(this->bucket_alloc().max_size() - 1);
}
template <class A, class G>
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
hash_buckets<A, G>::get_bucket(std::size_t num) const
{
return buckets_ + static_cast<std::ptrdiff_t>(num);
}
template <class A, class G>
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::bucket_ptr
hash_buckets<A, G>::bucket_ptr_from_hash(std::size_t hashed) const
{
return get_bucket(hashed % bucket_count_);
}
template <class A, class G>
std::size_t hash_buckets<A, G>::bucket_size(std::size_t index) const
{
if(!buckets_) return 0;
bucket_ptr ptr = get_bucket(index)->next_;
std::size_t count = 0;
while(ptr) {
++count;
ptr = ptr->next_;
}
return count;
}
template <class A, class G>
inline BOOST_DEDUCED_TYPENAME hash_buckets<A, G>::node_ptr
hash_buckets<A, G>::bucket_begin(std::size_t num) const
{
return buckets_ ? get_bucket(num)->next_ : node_ptr();
}
////////////////////////////////////////////////////////////////////////////
// Delete
template <class A, class G>
inline void hash_buckets<A, G>::delete_node(node_ptr b)
{
node* raw_ptr = static_cast<node*>(&*b);
boost::unordered_detail::destroy(&raw_ptr->value());
real_node_ptr n(node_alloc().address(*raw_ptr));
node_alloc().destroy(n);
node_alloc().deallocate(n, 1);
}
template <class A, class G>
inline void hash_buckets<A, G>::clear_bucket(bucket_ptr b)
{
node_ptr node_it = b->next_;
b->next_ = node_ptr();
while(node_it) {
node_ptr node_to_delete = node_it;
node_it = node_it->next_;
delete_node(node_to_delete);
}
}
template <class A, class G>
inline void hash_buckets<A, G>::delete_buckets()
{
bucket_ptr end = this->get_bucket(this->bucket_count_);
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
clear_bucket(begin);
}
// Destroy the buckets (including the sentinel bucket).
++end;
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
bucket_alloc().destroy(begin);
}
bucket_alloc().deallocate(this->buckets_, this->bucket_count_ + 1);
this->buckets_ = bucket_ptr();
}
template <class A, class G>
inline std::size_t hash_buckets<A, G>::delete_nodes(
node_ptr begin, node_ptr end)
{
std::size_t count = 0;
while(begin != end) {
node_ptr n = begin;
begin = begin->next_;
delete_node(n);
++count;
}
return count;
}
////////////////////////////////////////////////////////////////////////////
// Constructors and Destructors
template <class A, class G>
inline hash_buckets<A, G>::hash_buckets(
node_allocator const& a, std::size_t bucket_count)
: buckets_(),
bucket_count_(bucket_count),
allocators_(a,a)
{
}
template <class A, class G>
inline hash_buckets<A, G>::~hash_buckets()
{
if(this->buckets_) { this->delete_buckets(); }
}
template <class A, class G>
inline void hash_buckets<A, G>::create_buckets()
{
// The array constructor will clean up in the event of an
// exception.
allocator_array_constructor<bucket_allocator>
constructor(bucket_alloc());
// Creates an extra bucket to act as a sentinel.
constructor.construct(bucket(), this->bucket_count_ + 1);
// Set up the sentinel (node_ptr cast)
bucket_ptr sentinel = constructor.get() +
static_cast<std::ptrdiff_t>(this->bucket_count_);
sentinel->next_ = sentinel;
// Only release the buckets once everything is successfully
// done.
this->buckets_ = constructor.release();
}
////////////////////////////////////////////////////////////////////////////
// Constructors and Destructors
// no throw
template <class A, class G>
inline void hash_buckets<A, G>::move(hash_buckets& other)
{
BOOST_ASSERT(node_alloc() == other.node_alloc());
if(this->buckets_) { this->delete_buckets(); }
this->buckets_ = other.buckets_;
this->bucket_count_ = other.bucket_count_;
other.buckets_ = bucket_ptr();
other.bucket_count_ = 0;
}
template <class A, class G>
inline void hash_buckets<A, G>::swap(hash_buckets<A, G>& other)
{
BOOST_ASSERT(node_alloc() == other.node_alloc());
std::swap(buckets_, other.buckets_);
std::swap(bucket_count_, other.bucket_count_);
}
}}
#endif
-22
View File
@@ -1,22 +0,0 @@
// Copyright 2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_DETAIL_CONFIG_HEADER)
#define BOOST_UNORDERED_DETAIL_CONFIG_HEADER
#include <boost/config.hpp>
#if defined(BOOST_NO_SFINAE)
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#elif defined(__GNUC__) && \
(__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \
BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \
BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593))
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#endif
#endif
@@ -0,0 +1,304 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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)
#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
namespace boost { namespace unordered_detail {
template <class T>
class hash_equivalent_table : public T::table
{
public:
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME T::table table;
typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
typedef BOOST_DEDUCED_TYPENAME T::node node;
typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base;
typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
// Constructors
hash_equivalent_table(std::size_t n,
hasher const& hf, key_equal const& eq, value_allocator const& a)
: table(n, hf, eq, a) {}
hash_equivalent_table(hash_equivalent_table const& x)
: table(x, x.node_alloc()) {}
hash_equivalent_table(hash_equivalent_table const& x,
value_allocator const& a)
: table(x, a) {}
hash_equivalent_table(hash_equivalent_table& x, move_tag m)
: table(x, m) {}
hash_equivalent_table(hash_equivalent_table& x,
value_allocator const& a, move_tag m)
: table(x, a, m) {}
~hash_equivalent_table() {}
// Insert methods
iterator_base emplace_impl(node_constructor& a);
void emplace_impl_no_rehash(node_constructor& a);
// equals
bool equals(hash_equivalent_table const&) const;
inline node_ptr add_node(node_constructor& a,
bucket_ptr bucket, node_ptr pos);
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class... Args>
iterator_base emplace(Args&&... args);
#else
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
iterator_base emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)
#undef BOOST_UNORDERED_INSERT_IMPL
#endif
template <class I>
void insert_for_range(I i, I j, forward_traversal_tag);
template <class I>
void insert_for_range(I i, I j, boost::incrementable_traversal_tag);
template <class I>
void insert_range(I i, I j);
};
template <class H, class P, class A>
struct multiset : public types<
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME A::value_type,
H, P, A,
set_extractor<BOOST_DEDUCED_TYPENAME A::value_type>,
grouped>
{
typedef hash_equivalent_table<multiset<H, P, A> > impl;
typedef hash_table<multiset<H, P, A> > table;
};
template <class K, class H, class P, class A>
struct multimap : public types<
K, BOOST_DEDUCED_TYPENAME A::value_type,
H, P, A,
map_extractor<K, BOOST_DEDUCED_TYPENAME A::value_type>,
grouped>
{
typedef hash_equivalent_table<multimap<K, H, P, A> > impl;
typedef hash_table<multimap<K, H, P, A> > table;
};
////////////////////////////////////////////////////////////////////////////
// Equality
template <class T>
bool hash_equivalent_table<T>
::equals(hash_equivalent_table<T> const& other) const
{
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
bucket_ptr end = this->get_bucket(this->bucket_count_);
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
{
node_ptr it1 = i->next_;
while(BOOST_UNORDERED_BORLAND_BOOL(it1))
{
node_ptr it2 = other.find_iterator(this->get_key_from_ptr(it1));
if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
node_ptr end1 = node::next_group(it1);
node_ptr end2 = node::next_group(it2);
do {
if(!extractor::compare_mapped(
node::get_value(it1), node::get_value(it2)))
return false;
it1 = it1->next_;
it2 = it2->next_;
} while(it1 != end1 && it2 != end2);
if(it1 != end1 || it2 != end2) return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////
// A convenience method for adding nodes.
template <class T>
inline BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::node_ptr
hash_equivalent_table<T>
::add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos)
{
node_ptr n = a.release();
if(BOOST_UNORDERED_BORLAND_BOOL(pos)) {
node::add_after_node(n, pos);
}
else {
node::add_to_bucket(n, *bucket);
if(bucket < this->cached_begin_bucket_)
this->cached_begin_bucket_ = bucket;
}
++this->size_;
return n;
}
////////////////////////////////////////////////////////////////////////////
// Insert methods
template <class T>
inline BOOST_DEDUCED_TYPENAME
hash_equivalent_table<T>::iterator_base
hash_equivalent_table<T>::emplace_impl(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
std::size_t hash_value = this->hash_function()(k);
if(!this->size_) {
return this->emplace_empty_impl_with_node(a, 1);
}
else {
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr position = this->find_iterator(bucket, k);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
return iterator_base(bucket, add_node(a, bucket, position));
}
}
template <class T>
inline void hash_equivalent_table<T>
::emplace_impl_no_rehash(node_constructor& a)
{
key_type const& k = this->get_key(a.value());
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
add_node(a, bucket, this->find_iterator(bucket, k));
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
// Emplace (equivalent key containers)
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
// if hash function throws, basic exception safety
// strong otherwise
template <class T>
template <class... Args>
BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::iterator_base
hash_equivalent_table<T>
::emplace(Args&&... args)
{
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
return emplace_impl(a);
}
#else
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
BOOST_DEDUCED_TYPENAME hash_equivalent_table<T>::iterator_base \
hash_equivalent_table<T> \
::emplace(BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
return emplace_impl(a); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)
#undef BOOST_UNORDERED_INSERT_IMPL
#endif
////////////////////////////////////////////////////////////////////////////
// Insert range methods
// if hash function throws, or inserting > 1 element, basic exception safety
// strong otherwise
template <class T>
template <class I>
inline void hash_equivalent_table<T>
::insert_for_range(I i, I j, forward_traversal_tag)
{
if(i == j) return;
std::size_t distance = unordered_detail::distance(i, j);
if(distance == 1) {
emplace(*i);
}
else {
node_constructor a(*this);
// Only require basic exception safety here
if(this->size_) {
this->reserve_for_insert(this->size_ + distance);
}
else {
a.construct(*i++);
this->emplace_empty_impl_with_node(a, distance);
}
for (; i != j; ++i) {
a.construct(*i);
emplace_impl_no_rehash(a);
}
}
}
// if hash function throws, or inserting > 1 element, basic exception safety
// strong otherwise
template <class T>
template <class I>
inline void hash_equivalent_table<T>
::insert_for_range(I i, I j, boost::incrementable_traversal_tag)
{
node_constructor a(*this);
for (; i != j; ++i) {
a.construct(*i);
emplace_impl(a);
}
}
// if hash function throws, or inserting > 1 element, basic exception safety
// strong otherwise
template <class T>
template <class I>
void hash_equivalent_table<T>::insert_range(I i, I j)
{
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
iterator_traversal_tag;
insert_for_range(i, j, iterator_traversal_tag);
}
}}
#endif
@@ -0,0 +1,148 @@
// Copyright (C) 2005-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)
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost {
namespace unordered_detail {
// key extractors
//
// no throw
//
// 'extract_key' is called with the emplace parameters to return a
// key if available or 'no_key' is one isn't and will need to be
// constructed. This could be done by overloading the emplace implementation
// for the different cases, but that's a bit tricky on compilers without
// variadic templates.
struct no_key {
no_key() {}
template <class T> no_key(T const&) {}
};
template <class ValueType>
struct set_extractor
{
typedef ValueType value_type;
typedef ValueType key_type;
static key_type const& extract(key_type const& v)
{
return v;
}
static no_key extract()
{
return no_key();
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
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();
}
template <class Arg>
static no_key extract(Arg const&, Arg const&)
{
return no_key();
}
#endif
static bool compare_mapped(value_type const&, value_type const&)
{
return true;
}
};
template <class Key, class ValueType>
struct map_extractor
{
typedef ValueType value_type;
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Key>::type key_type;
static key_type const& extract(value_type const& v)
{
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)
{
return v.first;
}
template <class Second>
static key_type const& extract(
std::pair<key_type const, Second> const& v)
{
return v.first;
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
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&)
{
return k;
}
static no_key extract()
{
return no_key();
}
template <class Arg>
static no_key extract(Arg const&)
{
return no_key();
}
template <class Arg, class Arg1>
static no_key extract(Arg const&, Arg1 const&)
{
return no_key();
}
#endif
static bool compare_mapped(value_type const& x, value_type const& y)
{
return x.second == y.second;
}
};
}}
#endif
+856
View File
@@ -0,0 +1,856 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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)
// This contains the basic data structure, apart from the actual values. There's
// no construction or deconstruction here. So this only depends on the pointer
// type.
#ifndef BOOST_UNORDERED_DETAIL_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/compressed_pair.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <algorithm>
// This header defines most of the classes used to implement the unordered
// containers. It doesn't include the insert methods as they require a lot
// of preprocessor metaprogramming - they are in insert.hpp
// Template parameters:
//
// H = Hash Function
// P = Predicate
// A = Value Allocator
// G = Grouped/Ungrouped
// E = Key Extractor
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
# if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
// STLport doesn't have std::forward.
# else
# define BOOST_UNORDERED_STD_FORWARD
# endif
#endif
#if !defined(BOOST_UNORDERED_EMPLACE_LIMIT)
#define BOOST_UNORDERED_EMPLACE_LIMIT 10
#endif
#if !defined(BOOST_UNORDERED_STD_FORWARD)
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#define BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, class Arg)
#define BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
BOOST_PP_ENUM_BINARY_PARAMS_Z(z, num_params, Arg, const& arg)
#define BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, arg)
#endif
namespace boost { namespace unordered_detail {
static const float minimum_max_load_factor = 1e-3f;
static const std::size_t default_bucket_count = 11;
struct move_tag {};
template <class T> class hash_unique_table;
template <class T> class hash_equivalent_table;
template <class Alloc, class Grouped>
class hash_node_constructor;
template <class ValueType>
struct set_extractor;
template <class Key, class ValueType>
struct map_extractor;
struct no_key;
// 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
// hash_bucket
template <class A>
class hash_bucket
{
hash_bucket& operator=(hash_bucket const&);
public:
typedef hash_bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<A, bucket>::type
bucket_allocator;
typedef BOOST_DEDUCED_TYPENAME bucket_allocator::pointer bucket_ptr;
typedef bucket_ptr node_ptr;
node_ptr next_;
hash_bucket() : next_() {}
};
template <class A>
struct ungrouped_node_base : hash_bucket<A> {
typedef hash_bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
ungrouped_node_base() : bucket() {}
static inline node_ptr& next_group(node_ptr ptr);
static inline std::size_t group_count(node_ptr ptr);
static inline void add_to_bucket(node_ptr n, bucket& b);
static inline void add_after_node(node_ptr n, node_ptr position);
static void unlink_node(bucket& b, node_ptr n);
static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
static void unlink_nodes(bucket& b, node_ptr end);
};
template <class A>
struct grouped_node_base : hash_bucket<A>
{
typedef hash_bucket<A> bucket;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
node_ptr group_prev_;
grouped_node_base() : bucket(), group_prev_() {}
static inline node_ptr& next_group(node_ptr ptr);
static inline node_ptr first_in_group(node_ptr n);
static inline std::size_t group_count(node_ptr ptr);
static inline void add_to_bucket(node_ptr n, bucket& b);
static inline void add_after_node(node_ptr n, node_ptr position);
static void unlink_node(bucket& b, node_ptr n);
static void unlink_nodes(bucket& b, node_ptr begin, node_ptr end);
static void unlink_nodes(bucket& b, node_ptr end);
private:
static inline node_ptr split_group(node_ptr split);
static inline grouped_node_base& get(node_ptr ptr) {
return static_cast<grouped_node_base&>(*ptr);
}
};
struct ungrouped
{
template <class A>
struct base {
typedef ungrouped_node_base<A> type;
};
};
struct grouped
{
template <class A>
struct base {
typedef grouped_node_base<A> type;
};
};
template <class ValueType>
struct value_base
{
typedef ValueType value_type;
BOOST_DEDUCED_TYPENAME boost::aligned_storage<
sizeof(value_type),
::boost::alignment_of<value_type>::value>::type data_;
void* address() {
return this;
}
value_type& value() {
return *(ValueType*) this;
}
private:
value_base& operator=(value_base const&);
};
// Node
template <class A, class G>
class hash_node :
public G::BOOST_NESTED_TEMPLATE base<A>::type,
public value_base<BOOST_DEDUCED_TYPENAME A::value_type>
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME hash_bucket<A>::node_ptr node_ptr;
static value_type& get_value(node_ptr p) {
return static_cast<hash_node&>(*p).value();
}
private:
hash_node& operator=(hash_node const&);
};
// Iterator Base
template <class A, class G>
class hash_iterator_base
{
public:
typedef A value_allocator;
typedef hash_bucket<A> bucket;
typedef hash_node<A, G> node;
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
bucket_ptr bucket_;
node_ptr node_;
hash_iterator_base() : bucket_(), node_() {}
explicit hash_iterator_base(bucket_ptr b)
: bucket_(b),
node_(b ? b->next_ : node_ptr()) {}
hash_iterator_base(bucket_ptr b, node_ptr n)
: bucket_(b),
node_(n) {}
bool operator==(hash_iterator_base const& x) const {
return node_ == x.node_; }
bool operator!=(hash_iterator_base const& x) const {
return node_ != x.node_; }
value_type& operator*() const {
return node::get_value(node_);
}
void increment_bucket(node_ptr n) {
while(!n) {
++bucket_;
n = bucket_->next_;
}
node_ = bucket_ == n ? node_ptr() : n;
}
void increment() {
increment_bucket(node_->next_);
}
};
// hash_buckets
//
// This is responsible for allocating and deallocating buckets and nodes.
//
// Notes:
// 1. For the sake exception safety the allocators themselves don't allocate
// anything.
// 2. It's the callers responsibility to allocate the buckets before calling
// any of the methods (other than getters and setters).
template <class A, class G>
class hash_buckets
{
hash_buckets(hash_buckets const&);
hash_buckets& operator=(hash_buckets const&);
public:
// Types
typedef A value_allocator;
typedef hash_bucket<A> bucket;
typedef hash_iterator_base<A, G> iterator_base;
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME iterator_base::node node;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_allocator
bucket_allocator;
typedef BOOST_DEDUCED_TYPENAME bucket::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME bucket::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME rebind_wrap<value_allocator, node>::type
node_allocator;
typedef BOOST_DEDUCED_TYPENAME node_allocator::pointer real_node_ptr;
// Members
bucket_ptr buckets_;
std::size_t bucket_count_;
boost::compressed_pair<bucket_allocator, node_allocator> allocators_;
// Data access
bucket_allocator const& bucket_alloc() const {
return allocators_.first(); }
node_allocator const& node_alloc() const {
return allocators_.second(); }
bucket_allocator& bucket_alloc() {
return allocators_.first(); }
node_allocator& node_alloc() {
return allocators_.second(); }
std::size_t max_bucket_count() const;
// Constructors
hash_buckets(node_allocator const& a, std::size_t n);
void create_buckets();
~hash_buckets();
// no throw
void swap(hash_buckets& other);
void move(hash_buckets& other);
// For the remaining functions, buckets_ must not be null.
bucket_ptr get_bucket(std::size_t n) const;
bucket_ptr bucket_ptr_from_hash(std::size_t hashed) const;
std::size_t bucket_size(std::size_t index) const;
node_ptr bucket_begin(std::size_t n) const;
// Alloc/Dealloc
void delete_node(node_ptr);
//
void delete_buckets();
void clear_bucket(bucket_ptr);
std::size_t delete_nodes(node_ptr begin, node_ptr end);
std::size_t delete_to_bucket_end(node_ptr begin);
};
template <class H, class P> class set_hash_functions;
template <class H, class P>
class hash_buffered_functions
{
friend class set_hash_functions<H, P>;
hash_buffered_functions& operator=(hash_buffered_functions const&);
typedef boost::compressed_pair<H, P> function_pair;
typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
sizeof(function_pair),
::boost::alignment_of<function_pair>::value>::type aligned_function;
bool current_; // The currently active functions.
aligned_function funcs_[2];
function_pair const& current() const {
return *static_cast<function_pair const*>(
static_cast<void const*>(&funcs_[current_]));
}
void construct(bool which, H const& hf, P const& eq)
{
new((void*) &funcs_[which]) function_pair(hf, eq);
}
void construct(bool which, function_pair const& f)
{
new((void*) &funcs_[which]) function_pair(f);
}
void destroy(bool which)
{
boost::unordered_detail::destroy((function_pair*)(&funcs_[which]));
}
public:
hash_buffered_functions(H const& hf, P const& eq)
: current_(false)
{
construct(current_, hf, eq);
}
hash_buffered_functions(hash_buffered_functions const& bf)
: current_(false)
{
construct(current_, bf.current());
}
~hash_buffered_functions() {
destroy(current_);
}
H const& hash_function() const {
return current().first();
}
P const& key_eq() const {
return current().second();
}
};
template <class H, class P>
class set_hash_functions
{
set_hash_functions(set_hash_functions const&);
set_hash_functions& operator=(set_hash_functions const&);
typedef hash_buffered_functions<H, P> buffered_functions;
buffered_functions& buffered_functions_;
bool tmp_functions_;
public:
set_hash_functions(buffered_functions& f, H const& h, P const& p)
: buffered_functions_(f),
tmp_functions_(!f.current_)
{
f.construct(tmp_functions_, h, p);
}
set_hash_functions(buffered_functions& f,
buffered_functions const& other)
: buffered_functions_(f),
tmp_functions_(!f.current_)
{
f.construct(tmp_functions_, other.current());
}
~set_hash_functions()
{
buffered_functions_.destroy(tmp_functions_);
}
void commit()
{
buffered_functions_.current_ = tmp_functions_;
tmp_functions_ = !tmp_functions_;
}
};
template <class T>
class hash_table : public T::buckets, public T::buffered_functions
{
hash_table(hash_table const&);
public:
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME T::buffered_functions base;
typedef BOOST_DEDUCED_TYPENAME T::buckets buckets;
typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
typedef BOOST_DEDUCED_TYPENAME T::node node;
typedef BOOST_DEDUCED_TYPENAME T::bucket bucket;
typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base;
typedef BOOST_DEDUCED_TYPENAME T::node_allocator node_allocator;
typedef BOOST_DEDUCED_TYPENAME T::iterator_pair iterator_pair;
// Members
std::size_t size_;
float mlf_;
// Cached data - invalid if !this->buckets_
bucket_ptr cached_begin_bucket_;
std::size_t max_load_;
// Helper methods
key_type const& get_key(value_type const& v) const {
return extractor::extract(v);
}
key_type const& get_key_from_ptr(node_ptr n) const {
return extractor::extract(node::get_value(n));
}
bool equal(key_type const& k, value_type const& v) const;
template <class Key, class Pred>
node_ptr find_iterator(bucket_ptr bucket, Key const& k,
Pred const&) const;
node_ptr find_iterator(bucket_ptr bucket, key_type const& k) const;
node_ptr find_iterator(key_type const& k) const;
node_ptr* find_for_erase(bucket_ptr bucket, key_type const& k) const;
// Load methods
std::size_t max_size() const;
std::size_t bucket_index(key_type const& k) const;
void max_load_factor(float z);
std::size_t min_buckets_for_size(std::size_t n) const;
std::size_t calculate_max_load();
// Constructors
hash_table(std::size_t n, hasher const& hf, key_equal const& eq,
node_allocator const& a);
hash_table(hash_table const& x, node_allocator const& a);
hash_table(hash_table& x, move_tag m);
hash_table(hash_table& x, node_allocator const& a, move_tag m);
~hash_table() {}
hash_table& operator=(hash_table const&);
// Iterators
iterator_base begin() const {
return this->size_ ?
iterator_base(this->cached_begin_bucket_) :
iterator_base();
}
iterator_base end() const {
return iterator_base();
}
// Swap & Move
void swap(hash_table& x);
void fast_swap(hash_table& other);
void slow_swap(hash_table& other);
void partial_swap(hash_table& other);
void move(hash_table& x);
// Reserve and rehash
void create_for_insert(std::size_t n);
bool reserve_for_insert(std::size_t n);
void rehash(std::size_t n);
void rehash_impl(std::size_t n);
// Move/copy buckets
void move_buckets_to(buckets& dst);
void copy_buckets_to(buckets& dst) const;
// Misc. key methods
std::size_t count(key_type const& k) const;
iterator_base find(key_type const& k) const;
template <class Key, class Hash, class Pred>
iterator_base find(Key const& k, Hash const& h, Pred const& eq) const;
value_type& at(key_type const& k) const;
iterator_pair equal_range(key_type const& k) const;
// Erase
//
// no throw
void clear();
std::size_t erase_key(key_type const& k);
iterator_base erase_return_iterator(iterator_base r);
void erase(iterator_base r);
std::size_t erase_group(node_ptr* it, bucket_ptr bucket);
iterator_base erase_range(iterator_base r1, iterator_base r2);
// recompute_begin_bucket
void init_buckets();
// After an erase cached_begin_bucket_ might be left pointing to
// an empty bucket, so this is called to update it
//
// no throw
void recompute_begin_bucket(bucket_ptr b);
// This is called when a range has been erased
//
// no throw
void recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2);
// no throw
float load_factor() const;
iterator_base emplace_empty_impl_with_node(
node_constructor&, std::size_t);
};
// Iterator Access
#if !defined(__clang__)
class iterator_access
{
public:
template <class Iterator>
static BOOST_DEDUCED_TYPENAME Iterator::base const&
get(Iterator const& it)
{
return it.base_;
}
};
#else
class iterator_access
{
public:
// Note: we access Iterator::base here, rather than in the function
// signature to work around a bug in the friend support of an
// early version of clang.
template <class Iterator>
struct base
{
typedef BOOST_DEDUCED_TYPENAME Iterator::base type;
};
template <class Iterator>
static BOOST_DEDUCED_TYPENAME base<Iterator>::type const&
get(Iterator const& it)
{
return it.base_;
}
};
#endif
// Iterators
template <class A, class G> class hash_iterator;
template <class A, class G> class hash_const_iterator;
template <class A, class G> class hash_local_iterator;
template <class A, class G> class hash_const_local_iterator;
// Local Iterators
//
// all no throw
template <class A, class G>
class hash_local_iterator
: public boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME A::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME A::pointer,
BOOST_DEDUCED_TYPENAME A::reference>
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
private:
typedef hash_buckets<A, G> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef hash_const_local_iterator<A, G> const_local_iterator;
friend class hash_const_local_iterator<A, G>;
node_ptr ptr_;
public:
hash_local_iterator() : ptr_() {}
explicit hash_local_iterator(node_ptr x) : ptr_(x) {}
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
return node::get_value(ptr_);
}
value_type* operator->() const {
return &node::get_value(ptr_);
}
hash_local_iterator& operator++() {
ptr_ = ptr_->next_; return *this;
}
hash_local_iterator operator++(int) {
hash_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp; }
bool operator==(hash_local_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator==(const_local_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator!=(hash_local_iterator x) const {
return ptr_ != x.ptr_;
}
bool operator!=(const_local_iterator x) const {
return ptr_ != x.ptr_;
}
};
template <class A, class G>
class hash_const_local_iterator
: public boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME A::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME A::const_pointer,
BOOST_DEDUCED_TYPENAME A::const_reference >
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
private:
typedef hash_buckets<A, G> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef hash_local_iterator<A, G> local_iterator;
friend class hash_local_iterator<A, G>;
ptr ptr_;
public:
hash_const_local_iterator() : ptr_() {}
explicit hash_const_local_iterator(ptr x) : ptr_(x) {}
hash_const_local_iterator(local_iterator x) : ptr_(x.ptr_) {}
BOOST_DEDUCED_TYPENAME A::const_reference
operator*() const {
return node::get_value(ptr_);
}
value_type const* operator->() const {
return &node::get_value(ptr_);
}
hash_const_local_iterator& operator++() {
ptr_ = ptr_->next_; return *this;
}
hash_const_local_iterator operator++(int) {
hash_const_local_iterator tmp(ptr_); ptr_ = ptr_->next_; return tmp;
}
bool operator==(local_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator==(hash_const_local_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator!=(local_iterator x) const {
return ptr_ != x.ptr_;
}
bool operator!=(hash_const_local_iterator x) const {
return ptr_ != x.ptr_;
}
};
// iterators
//
// all no throw
template <class A, class G>
class hash_iterator
: public boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME A::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME A::pointer,
BOOST_DEDUCED_TYPENAME A::reference >
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
private:
typedef hash_buckets<A, G> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base base;
typedef hash_const_iterator<A, G> const_iterator;
friend class hash_const_iterator<A, G>;
base base_;
public:
hash_iterator() : base_() {}
explicit hash_iterator(base const& x) : base_(x) {}
BOOST_DEDUCED_TYPENAME A::reference operator*() const {
return *base_;
}
value_type* operator->() const {
return &*base_;
}
hash_iterator& operator++() {
base_.increment(); return *this;
}
hash_iterator operator++(int) {
hash_iterator tmp(base_); base_.increment(); return tmp;
}
bool operator==(hash_iterator const& x) const {
return base_ == x.base_;
}
bool operator==(const_iterator const& x) const {
return base_ == x.base_;
}
bool operator!=(hash_iterator const& x) const {
return base_ != x.base_;
}
bool operator!=(const_iterator const& x) const {
return base_ != x.base_;
}
};
template <class A, class G>
class hash_const_iterator
: public boost::iterator <
std::forward_iterator_tag,
BOOST_DEDUCED_TYPENAME A::value_type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME A::const_pointer,
BOOST_DEDUCED_TYPENAME A::const_reference >
{
public:
typedef BOOST_DEDUCED_TYPENAME A::value_type value_type;
private:
typedef hash_buckets<A, G> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base base;
typedef hash_iterator<A, G> iterator;
friend class hash_iterator<A, G>;
friend class iterator_access;
base base_;
public:
hash_const_iterator() : base_() {}
explicit hash_const_iterator(base const& x) : base_(x) {}
hash_const_iterator(iterator const& x) : base_(x.base_) {}
BOOST_DEDUCED_TYPENAME A::const_reference operator*() const {
return *base_;
}
value_type const* operator->() const {
return &*base_;
}
hash_const_iterator& operator++() {
base_.increment(); return *this;
}
hash_const_iterator operator++(int) {
hash_const_iterator tmp(base_); base_.increment(); return tmp;
}
bool operator==(iterator const& x) const {
return base_ == x.base_;
}
bool operator==(hash_const_iterator const& x) const {
return base_ == x.base_;
}
bool operator!=(iterator const& x) const {
return base_ != x.base_;
}
bool operator!=(hash_const_iterator const& x) const {
return base_ != x.base_;
}
};
// types
template <class K, class V, class H, class P, class A, class E, class G>
struct types
{
public:
typedef K key_type;
typedef V value_type;
typedef H hasher;
typedef P key_equal;
typedef A value_allocator;
typedef E extractor;
typedef G group_type;
typedef hash_node_constructor<value_allocator, group_type>
node_constructor;
typedef hash_buckets<value_allocator, group_type> buckets;
typedef hash_buffered_functions<hasher, key_equal> buffered_functions;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef BOOST_DEDUCED_TYPENAME buckets::bucket bucket;
typedef BOOST_DEDUCED_TYPENAME buckets::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base iterator_base;
typedef BOOST_DEDUCED_TYPENAME buckets::node_allocator node_allocator;
typedef std::pair<iterator_base, iterator_base> iterator_pair;
};
}}
#endif
@@ -1,304 +0,0 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2008 Daniel James
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <cstddef>
#include <boost/config/no_tr1/cmath.hpp>
#include <algorithm>
#include <utility>
#include <stdexcept>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/limits.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/utility/swap.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/not.hpp>
#endif
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0582)
#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
#else
#define BOOST_UNORDERED_BORLAND_BOOL(x) x
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
#define BOOST_UNORDERED_MSVC_RESET_PTR(x) unordered_detail::reset(x)
#else
#define BOOST_UNORDERED_MSVC_RESET_PTR(x)
#endif
namespace boost {
namespace unordered_detail {
template <class T> struct type_wrapper {};
static const std::size_t default_initial_bucket_count = 50;
static const float minimum_max_load_factor = 1e-3f;
inline std::size_t double_to_size_t(double f)
{
return f >= static_cast<double>((std::numeric_limits<std::size_t>::max)()) ?
(std::numeric_limits<std::size_t>::max)() :
static_cast<std::size_t>(f);
}
// prime number list, accessor
template<typename T> struct prime_list_template
{
static std::size_t const value[];
static std::ptrdiff_t const length;
};
template<typename T>
std::size_t const prime_list_template<T>::value[] = {
5ul, 11ul, 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,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul };
template<typename T>
std::ptrdiff_t const prime_list_template<T>::length = 28;
typedef prime_list_template<std::size_t> prime_list;
// no throw
inline std::size_t next_prime(std::size_t n) {
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin +
prime_list::length;
std::size_t const* bound =
std::lower_bound(prime_list_begin, prime_list_end, n);
if(bound == prime_list_end)
bound--;
return *bound;
}
// no throw
inline std::size_t prev_prime(std::size_t n) {
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin +
prime_list::length;
std::size_t const* bound =
std::upper_bound(prime_list_begin,prime_list_end, n);
if(bound != prime_list_begin)
bound--;
return *bound;
}
// Controls how many buckets are allocated and which buckets hash
// values map to. Does not contain the buckets themselves, or ever
// deal with them directly.
struct bucket_manager {
std::size_t bucket_count_;
bucket_manager()
: bucket_count_(0) {}
explicit bucket_manager(std::size_t n)
: bucket_count_(next_prime(n)) {}
std::size_t bucket_count() const {
return bucket_count_;
}
std::size_t bucket_from_hash(std::size_t hashed) const {
return hashed % bucket_count_;
}
std::size_t max_bucket_count(std::size_t max_size) const {
return prev_prime(max_size);
}
};
// pair_cast - used to convert between pair types.
template <class Dst1, class Dst2, class Src1, class Src2>
inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
{
return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
}
#if !defined(BOOST_NO_STD_DISTANCE)
using ::std::distance;
#else
template <class ForwardIterator>
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
std::size_t x;
std::distance(i, j, x);
return x;
}
#endif
struct move_tag {};
// Both hasher and key_equal's copy/assign can throw so double
// buffering is used to copy them.
template <typename Hash, typename Pred>
struct buffered_functions
{
typedef Hash hasher;
typedef Pred key_equal;
class functions
{
std::pair<hasher, key_equal> functions_;
public:
functions(hasher const& h, key_equal const& k)
: functions_(h, k) {}
hasher const& hash_function() const
{
return functions_.first;
}
key_equal const& key_eq() const
{
return functions_.second;
}
};
typedef functions buffered_functions::*functions_ptr;
buffered_functions(hasher const& h, key_equal const& k)
: func1_(h, k), func2_(h, k), func_(&buffered_functions::func1_) {}
// This copies the given function objects into the currently unused
// function objects and returns a pointer, that func_ can later be
// set to, to commit the change.
//
// Strong exception safety (since only usued function objects are
// changed).
functions_ptr buffer(buffered_functions const& x) {
functions_ptr ptr = func_ == &buffered_functions::func1_
? &buffered_functions::func2_ : &buffered_functions::func1_;
this->*ptr = x.current();
return ptr;
}
void set(functions_ptr ptr) {
BOOST_ASSERT(ptr != func_);
func_ = ptr;
}
functions const& current() const {
return this->*func_;
}
private:
functions func1_;
functions func2_;
functions_ptr func_; // The currently active functions.
};
template <typename T>
void destroy(T* x) {
x->~T();
}
}
}
#define BOOST_UNORDERED_EQUIVALENT_KEYS 1
#include <boost/unordered/detail/hash_table_impl.hpp>
#undef BOOST_UNORDERED_EQUIVALENT_KEYS
#define BOOST_UNORDERED_EQUIVALENT_KEYS 0
#include <boost/unordered/detail/hash_table_impl.hpp>
#undef BOOST_UNORDERED_EQUIVALENT_KEYS
namespace boost {
namespace unordered_detail {
class iterator_access
{
public:
template <class Iterator>
static BOOST_DEDUCED_TYPENAME Iterator::base const& get(Iterator const& it) {
return it.base_;
}
};
template <class ValueType, class KeyType,
class Hash, class Pred, class Alloc>
class hash_types_unique_keys
{
public:
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, ValueType>::type
value_allocator;
typedef hash_table_unique_keys<ValueType, KeyType, Hash, Pred,
value_allocator> hash_table;
typedef hash_table_data_unique_keys<value_allocator> data;
typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base;
typedef hash_const_local_iterator_unique_keys<value_allocator> const_local_iterator;
typedef hash_local_iterator_unique_keys<value_allocator> local_iterator;
typedef hash_const_iterator_unique_keys<value_allocator> const_iterator;
typedef hash_iterator_unique_keys<value_allocator> iterator;
typedef BOOST_DEDUCED_TYPENAME data::size_type size_type;
typedef std::ptrdiff_t difference_type;
};
template <class ValueType, class KeyType,
class Hash, class Pred, class Alloc>
class hash_types_equivalent_keys
{
public:
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc, ValueType>::type
value_allocator;
typedef hash_table_equivalent_keys<ValueType, KeyType, Hash, Pred,
value_allocator> hash_table;
typedef hash_table_data_equivalent_keys<value_allocator> data;
typedef BOOST_DEDUCED_TYPENAME data::iterator_base iterator_base;
typedef hash_const_local_iterator_equivalent_keys<value_allocator> const_local_iterator;
typedef hash_local_iterator_equivalent_keys<value_allocator> local_iterator;
typedef hash_const_iterator_equivalent_keys<value_allocator> const_iterator;
typedef hash_iterator_equivalent_keys<value_allocator> iterator;
typedef BOOST_DEDUCED_TYPENAME data::size_type size_type;
typedef std::ptrdiff_t difference_type;
};
} // namespace boost::unordered_detail
} // namespace boost
#undef BOOST_UNORDERED_BORLAND_BOOL
#undef BOOST_UNORDERED_MSVC_RESET_PTR
#endif // BOOST_UNORDERED_DETAIL_HASH_TABLE_HPP_INCLUDED
File diff suppressed because it is too large Load Diff
+17 -2
View File
@@ -11,7 +11,7 @@
#ifndef BOOST_UNORDERED_DETAIL_MOVE_HEADER
#define BOOST_UNORDERED_DETAIL_MOVE_HEADER
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
@@ -20,7 +20,20 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/unordered/detail/config.hpp>
#include <boost/detail/workaround.hpp>
/*************************************************************************************************/
#if defined(BOOST_NO_SFINAE)
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#elif defined(__GNUC__) && \
(__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \
BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \
BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593))
# define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN
#endif
/*************************************************************************************************/
@@ -96,6 +109,8 @@ struct move_from
{
explicit move_from(T& x) : source(x) { }
T& source;
private:
move_from& operator=(move_from const&);
};
/*************************************************************************************************/
+226
View File
@@ -0,0 +1,226 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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)
// This contains the basic data structure, apart from the actual values. There's
// no construction or deconstruction here. So this only depends on the pointer
// type.
#ifndef BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_NODE_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/unordered/detail/fwd.hpp>
#if BOOST_WORKAROUND(__BORLANDC__, <= 0X0582)
#define BOOST_UNORDERED_BORLAND_BOOL(x) (bool)(x)
#else
#define BOOST_UNORDERED_BORLAND_BOOL(x) x
#endif
namespace boost { namespace unordered_detail {
////////////////////////////////////////////////////////////////////////////
// ungrouped node implementation
template <class A>
inline BOOST_DEDUCED_TYPENAME ungrouped_node_base<A>::node_ptr&
ungrouped_node_base<A>::next_group(node_ptr ptr)
{
return ptr->next_;
}
template <class A>
inline std::size_t ungrouped_node_base<A>::group_count(node_ptr)
{
return 1;
}
template <class A>
inline void ungrouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
{
n->next_ = b.next_;
b.next_ = n;
}
template <class A>
inline void ungrouped_node_base<A>::add_after_node(node_ptr n,
node_ptr position)
{
n->next_ = position->next_;
position->next_ = position;
}
template <class A>
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b,
node_ptr begin, node_ptr end)
{
node_ptr* pos = &b.next_;
while(*pos != begin) pos = &(*pos)->next_;
*pos = end;
}
template <class A>
inline void ungrouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
{
b.next_ = end;
}
template <class A>
inline void ungrouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
{
unlink_nodes(b, n, n->next_);
}
////////////////////////////////////////////////////////////////////////////
// grouped node implementation
// If ptr is the first element in a group, return pointer to next group.
// Otherwise returns a pointer to ptr.
template <class A>
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr&
grouped_node_base<A>::next_group(node_ptr ptr)
{
return get(ptr).group_prev_->next_;
}
template <class A>
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
grouped_node_base<A>::first_in_group(node_ptr ptr)
{
while(next_group(ptr) == ptr)
ptr = get(ptr).group_prev_;
return ptr;
}
template <class A>
inline std::size_t grouped_node_base<A>::group_count(node_ptr ptr)
{
node_ptr start = ptr;
std::size_t size = 0;
do {
++size;
ptr = get(ptr).group_prev_;
} while(ptr != start);
return size;
}
template <class A>
inline void grouped_node_base<A>::add_to_bucket(node_ptr n, bucket& b)
{
n->next_ = b.next_;
get(n).group_prev_ = n;
b.next_ = n;
}
template <class A>
inline void grouped_node_base<A>::add_after_node(node_ptr n, node_ptr pos)
{
n->next_ = next_group(pos);
get(n).group_prev_ = get(pos).group_prev_;
next_group(pos) = n;
get(pos).group_prev_ = n;
}
// 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).
template <class A>
inline BOOST_DEDUCED_TYPENAME grouped_node_base<A>::node_ptr
grouped_node_base<A>::split_group(node_ptr split)
{
node_ptr first = first_in_group(split);
if(first == split) return split;
node_ptr last = get(first).group_prev_;
get(first).group_prev_ = get(split).group_prev_;
get(split).group_prev_ = last;
return first;
}
template <class A>
void grouped_node_base<A>::unlink_node(bucket& b, node_ptr n)
{
node_ptr next = n->next_;
node_ptr* pos = &next_group(n);
if(*pos != n) {
// The node is at the beginning of a group.
// Find the previous node pointer:
pos = &b.next_;
while(*pos != n) pos = &next_group(*pos);
// Remove from group
if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
get(next).group_prev_ == n)
{
get(next).group_prev_ = get(n).group_prev_;
}
}
else if(BOOST_UNORDERED_BORLAND_BOOL(next) &&
get(next).group_prev_ == n)
{
// The deleted node is not at the end of the group, so
// change the link from the next node.
get(next).group_prev_ = get(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_ptr x = get(n).group_prev_;
while(get(x).group_prev_ != n) {
x = get(x).group_prev_;
}
get(x).group_prev_ = get(n).group_prev_;
}
*pos = next;
}
template <class A>
void grouped_node_base<A>::unlink_nodes(bucket& b,
node_ptr begin, node_ptr end)
{
node_ptr* pos = &next_group(begin);
if(*pos != begin) {
// The node is at the beginning of a group.
// Find the previous node pointer:
pos = &b.next_;
while(*pos != begin) pos = &next_group(*pos);
// Remove from group
if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end);
}
else {
node_ptr group1 = split_group(begin);
if(BOOST_UNORDERED_BORLAND_BOOL(end)) {
node_ptr group2 = split_group(end);
if(begin == group2) {
node_ptr end1 = get(group1).group_prev_;
node_ptr end2 = get(group2).group_prev_;
get(group1).group_prev_ = end2;
get(group2).group_prev_ = end1;
}
}
}
*pos = end;
}
template <class A>
void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end)
{
split_group(end);
b.next_ = end;
}
}}
#endif
+778
View File
@@ -0,0 +1,778 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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)
#ifndef BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
#include <cstddef>
#include <stdexcept>
#include <algorithm>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/throw_exception.hpp>
#include <boost/unordered/detail/buckets.hpp>
namespace boost { namespace unordered_detail {
////////////////////////////////////////////////////////////////////////////
// Helper methods
// strong exception safety, no side effects
template <class T>
inline bool hash_table<T>::equal(
key_type const& k, value_type const& v) const
{
return this->key_eq()(k, get_key(v));
}
// strong exception safety, no side effects
template <class T>
template <class Key, class Pred>
inline BOOST_DEDUCED_TYPENAME T::node_ptr
hash_table<T>::find_iterator(bucket_ptr bucket, Key const& k,
Pred const& eq) const
{
node_ptr it = bucket->next_;
while (BOOST_UNORDERED_BORLAND_BOOL(it) &&
!eq(k, get_key(node::get_value(it))))
{
it = node::next_group(it);
}
return it;
}
// strong exception safety, no side effects
template <class T>
inline BOOST_DEDUCED_TYPENAME T::node_ptr
hash_table<T>::find_iterator(
bucket_ptr bucket, key_type const& k) const
{
node_ptr it = bucket->next_;
while (BOOST_UNORDERED_BORLAND_BOOL(it) &&
!equal(k, node::get_value(it)))
{
it = node::next_group(it);
}
return it;
}
// strong exception safety, no side effects
// pre: this->buckets_
template <class T>
inline BOOST_DEDUCED_TYPENAME T::node_ptr
hash_table<T>::find_iterator(key_type const& k) const
{
return find_iterator(this->get_bucket(this->bucket_index(k)), k);
}
// strong exception safety, no side effects
template <class T>
inline BOOST_DEDUCED_TYPENAME T::node_ptr*
hash_table<T>::find_for_erase(
bucket_ptr bucket, key_type const& k) const
{
node_ptr* it = &bucket->next_;
while(BOOST_UNORDERED_BORLAND_BOOL(*it) &&
!equal(k, node::get_value(*it)))
{
it = &node::next_group(*it);
}
return it;
}
////////////////////////////////////////////////////////////////////////////
// Load methods
// no throw
template <class T>
std::size_t hash_table<T>::max_size() const
{
using namespace std;
// size < mlf_ * count
return double_to_size_t(ceil(
(double) this->mlf_ * this->max_bucket_count())) - 1;
}
// strong safety
template <class T>
inline std::size_t hash_table<T>::bucket_index(
key_type const& k) const
{
// hash_function can throw:
return this->hash_function()(k) % this->bucket_count_;
}
// no throw
template <class T>
inline std::size_t hash_table<T>::calculate_max_load()
{
using namespace std;
// From 6.3.1/13:
// Only resize when size >= mlf_ * count
return double_to_size_t(ceil((double) mlf_ * this->bucket_count_));
}
template <class T>
void hash_table<T>::max_load_factor(float z)
{
BOOST_ASSERT(z > 0);
mlf_ = (std::max)(z, minimum_max_load_factor);
this->max_load_ = this->calculate_max_load();
}
// no throw
template <class T>
inline std::size_t hash_table<T>::min_buckets_for_size(
std::size_t size) const
{
BOOST_ASSERT(this->mlf_ != 0);
using namespace std;
// From 6.3.1/13:
// size < mlf_ * count
// => count > size / mlf_
//
// Or from rehash post-condition:
// count > size / mlf_
return next_prime(double_to_size_t(floor(size / (double) mlf_)) + 1);
}
////////////////////////////////////////////////////////////////////////////
// recompute_begin_bucket
// init_buckets
template <class T>
inline void hash_table<T>::init_buckets()
{
if (this->size_) {
this->cached_begin_bucket_ = this->buckets_;
while (!this->cached_begin_bucket_->next_)
++this->cached_begin_bucket_;
} else {
this->cached_begin_bucket_ = this->get_bucket(this->bucket_count_);
}
this->max_load_ = calculate_max_load();
}
// After an erase cached_begin_bucket_ might be left pointing to
// an empty bucket, so this is called to update it
//
// no throw
template <class T>
inline void hash_table<T>::recompute_begin_bucket(bucket_ptr b)
{
BOOST_ASSERT(!(b < this->cached_begin_bucket_));
if(b == this->cached_begin_bucket_)
{
if (this->size_ != 0) {
while (!this->cached_begin_bucket_->next_)
++this->cached_begin_bucket_;
} else {
this->cached_begin_bucket_ =
this->get_bucket(this->bucket_count_);
}
}
}
// This is called when a range has been erased
//
// no throw
template <class T>
inline void hash_table<T>::recompute_begin_bucket(
bucket_ptr b1, bucket_ptr b2)
{
BOOST_ASSERT(!(b1 < this->cached_begin_bucket_) && !(b2 < b1));
BOOST_ASSERT(BOOST_UNORDERED_BORLAND_BOOL(b2->next_));
if(b1 == this->cached_begin_bucket_ && !b1->next_)
this->cached_begin_bucket_ = b2;
}
// no throw
template <class T>
inline float hash_table<T>::load_factor() const
{
BOOST_ASSERT(this->bucket_count_ != 0);
return static_cast<float>(this->size_)
/ static_cast<float>(this->bucket_count_);
}
////////////////////////////////////////////////////////////////////////////
// Constructors
template <class T>
hash_table<T>::hash_table(std::size_t num_buckets,
hasher const& hf, key_equal const& eq, node_allocator const& a)
: buckets(a, next_prime(num_buckets)),
base(hf, eq),
size_(),
mlf_(1.0f),
cached_begin_bucket_(),
max_load_(0)
{
}
// Copy Construct with allocator
template <class T>
hash_table<T>::hash_table(hash_table const& x,
node_allocator const& a)
: buckets(a, x.min_buckets_for_size(x.size_)),
base(x),
size_(x.size_),
mlf_(x.mlf_),
cached_begin_bucket_(),
max_load_(0)
{
if(x.size_) {
x.copy_buckets_to(*this);
this->init_buckets();
}
}
// Move Construct
template <class T>
hash_table<T>::hash_table(hash_table& x, move_tag)
: buckets(x.node_alloc(), x.bucket_count_),
base(x),
size_(0),
mlf_(1.0f),
cached_begin_bucket_(),
max_load_(0)
{
this->partial_swap(x);
}
template <class T>
hash_table<T>::hash_table(hash_table& x,
node_allocator const& a, move_tag)
: buckets(a, x.bucket_count_),
base(x),
size_(0),
mlf_(x.mlf_),
cached_begin_bucket_(),
max_load_(0)
{
if(a == x.node_alloc()) {
this->partial_swap(x);
}
else if(x.size_) {
x.copy_buckets_to(*this);
this->size_ = x.size_;
this->init_buckets();
}
}
template <class T>
hash_table<T>& hash_table<T>::operator=(
hash_table const& x)
{
hash_table tmp(x, this->node_alloc());
this->fast_swap(tmp);
return *this;
}
////////////////////////////////////////////////////////////////////////////
// Swap & Move
// Swap
//
// Strong exception safety
//
// Can throw if hash or predicate object's copy constructor throws
// or if allocators are unequal.
template <class T>
inline void hash_table<T>::partial_swap(hash_table& x)
{
this->buckets::swap(x); // No throw
std::swap(this->size_, x.size_);
std::swap(this->mlf_, x.mlf_);
std::swap(this->cached_begin_bucket_, x.cached_begin_bucket_);
std::swap(this->max_load_, x.max_load_);
}
template <class T>
inline void hash_table<T>::fast_swap(hash_table& x)
{
// These can throw, but they only affect the function objects
// that aren't in use so it is strongly exception safe, via.
// double buffering.
{
set_hash_functions<hasher, key_equal> op1(*this, x);
set_hash_functions<hasher, key_equal> op2(x, *this);
op1.commit();
op2.commit();
}
this->buckets::swap(x); // No throw
std::swap(this->size_, x.size_);
std::swap(this->mlf_, x.mlf_);
std::swap(this->cached_begin_bucket_, x.cached_begin_bucket_);
std::swap(this->max_load_, x.max_load_);
}
template <class T>
inline void hash_table<T>::slow_swap(hash_table& x)
{
if(this == &x) return;
{
// These can throw, but they only affect the function objects
// that aren't in use so it is strongly exception safe, via.
// double buffering.
set_hash_functions<hasher, key_equal> op1(*this, x);
set_hash_functions<hasher, key_equal> op2(x, *this);
// Create new buckets in separate hash_buckets objects
// which will clean up if anything throws an exception.
// (all can throw, but with no effect as these are new objects).
buckets b1(this->node_alloc(), x.min_buckets_for_size(x.size_));
if(x.size_) x.copy_buckets_to(b1);
buckets b2(x.node_alloc(), this->min_buckets_for_size(this->size_));
if(this->size_) copy_buckets_to(b2);
// Modifying the data, so no throw from now on.
b1.swap(*this);
b2.swap(x);
op1.commit();
op2.commit();
}
std::swap(this->size_, x.size_);
if(this->buckets_) this->init_buckets();
if(x.buckets_) x.init_buckets();
}
template <class T>
void hash_table<T>::swap(hash_table& x)
{
if(this->node_alloc() == x.node_alloc()) {
if(this != &x) this->fast_swap(x);
}
else {
this->slow_swap(x);
}
}
// Move
//
// Strong exception safety (might change unused function objects)
//
// Can throw if hash or predicate object's copy constructor throws
// or if allocators are unequal.
template <class T>
void hash_table<T>::move(hash_table& x)
{
// This can throw, but it only affects the function objects
// that aren't in use so it is strongly exception safe, via.
// double buffering.
set_hash_functions<hasher, key_equal> new_func_this(*this, x);
if(this->node_alloc() == x.node_alloc()) {
this->buckets::move(x); // no throw
this->size_ = x.size_;
this->cached_begin_bucket_ = x.cached_begin_bucket_;
this->max_load_ = x.max_load_;
x.size_ = 0;
}
else {
// Create new buckets in separate HASH_TABLE_DATA objects
// which will clean up if anything throws an exception.
// (all can throw, but with no effect as these are new objects).
buckets b(this->node_alloc(), x.min_buckets_for_size(x.size_));
if(x.size_) x.copy_buckets_to(b);
// Start updating the data here, no throw from now on.
this->size_ = x.size_;
b.swap(*this);
this->init_buckets();
}
// We've made it, the rest is no throw.
this->mlf_ = x.mlf_;
new_func_this.commit();
}
////////////////////////////////////////////////////////////////////////////
// Reserve & Rehash
// basic exception safety
template <class T>
inline void hash_table<T>::create_for_insert(std::size_t size)
{
this->bucket_count_ = (std::max)(this->bucket_count_,
this->min_buckets_for_size(size));
this->create_buckets();
this->init_buckets();
}
// basic exception safety
template <class T>
inline bool hash_table<T>::reserve_for_insert(std::size_t size)
{
if(size >= max_load_) {
std::size_t num_buckets
= this->min_buckets_for_size((std::max)(size,
this->size_ + (this->size_ >> 1)));
if(num_buckets != this->bucket_count_) {
rehash_impl(num_buckets);
return true;
}
}
return false;
}
// if hash function throws, basic exception safety
// strong otherwise.
template <class T>
inline void hash_table<T>::rehash(std::size_t min_buckets)
{
using namespace std;
if(!this->size_) {
if(this->buckets_) this->delete_buckets();
this->bucket_count_ = next_prime(min_buckets);
}
else {
// no throw:
min_buckets = next_prime((std::max)(min_buckets,
double_to_size_t(floor(this->size_ / (double) mlf_)) + 1));
if(min_buckets != this->bucket_count_) rehash_impl(min_buckets);
}
}
// if hash function throws, basic exception safety
// strong otherwise
template <class T>
void hash_table<T>
::rehash_impl(std::size_t num_buckets)
{
hasher const& hf = this->hash_function();
std::size_t size = this->size_;
bucket_ptr end = this->get_bucket(this->bucket_count_);
buckets dst(this->node_alloc(), num_buckets);
dst.create_buckets();
buckets src(this->node_alloc(), this->bucket_count_);
src.swap(*this);
this->size_ = 0;
for(bucket_ptr bucket = this->cached_begin_bucket_;
bucket != end; ++bucket)
{
node_ptr group = bucket->next_;
while(group) {
// Move the first group of equivalent nodes in bucket to dst.
// This next line throws iff the hash function throws.
bucket_ptr dst_bucket = dst.bucket_ptr_from_hash(
hf(get_key_from_ptr(group)));
node_ptr& next_group = node::next_group(group);
bucket->next_ = next_group;
next_group = dst_bucket->next_;
dst_bucket->next_ = group;
group = bucket->next_;
}
}
// Swap the new nodes back into the container and setup the local
// variables.
this->size_ = size;
dst.swap(*this); // no throw
this->init_buckets();
}
////////////////////////////////////////////////////////////////////////////
// copy_buckets_to
// copy_buckets_to
//
// basic excpetion safety. If an exception is thrown this will
// leave dst partially filled.
template <class T>
void hash_table<T>
::copy_buckets_to(buckets& dst) const
{
BOOST_ASSERT(this->buckets_ && !dst.buckets_);
hasher const& hf = this->hash_function();
bucket_ptr end = this->get_bucket(this->bucket_count_);
node_constructor a(dst);
dst.create_buckets();
// no throw:
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i) {
// no throw:
for(node_ptr it = i->next_; it;) {
// hash function can throw.
bucket_ptr dst_bucket = dst.bucket_ptr_from_hash(
hf(get_key_from_ptr(it)));
// throws, strong
node_ptr group_end = node::next_group(it);
a.construct(node::get_value(it));
node_ptr n = a.release();
node::add_to_bucket(n, *dst_bucket);
for(it = it->next_; it != group_end; it = it->next_) {
a.construct(node::get_value(it));
node::add_after_node(a.release(), n);
}
}
}
}
////////////////////////////////////////////////////////////////////////////
// Misc. key methods
// strong exception safety
// count
//
// strong exception safety, no side effects
template <class T>
std::size_t hash_table<T>::count(key_type const& k) const
{
if(!this->size_) return 0;
node_ptr it = find_iterator(k); // throws, strong
return BOOST_UNORDERED_BORLAND_BOOL(it) ? node::group_count(it) : 0;
}
// find
//
// strong exception safety, no side effects
template <class T>
BOOST_DEDUCED_TYPENAME T::iterator_base
hash_table<T>::find(key_type const& k) const
{
if(!this->size_) return this->end();
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
node_ptr it = find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(it))
return iterator_base(bucket, it);
else
return this->end();
}
template <class T>
template <class Key, class Hash, class Pred>
BOOST_DEDUCED_TYPENAME T::iterator_base hash_table<T>::find(Key const& k,
Hash const& h, Pred const& eq) const
{
if(!this->size_) return this->end();
bucket_ptr bucket = this->get_bucket(h(k) % this->bucket_count_);
node_ptr it = find_iterator(bucket, k, eq);
if (BOOST_UNORDERED_BORLAND_BOOL(it))
return iterator_base(bucket, it);
else
return this->end();
}
template <class T>
BOOST_DEDUCED_TYPENAME T::value_type&
hash_table<T>::at(key_type const& k) const
{
if(!this->size_)
boost::throw_exception(std::out_of_range("Unable to find key in unordered_map."));
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
node_ptr it = find_iterator(bucket, k);
if (!it)
boost::throw_exception(std::out_of_range("Unable to find key in unordered_map."));
return node::get_value(it);
}
// equal_range
//
// strong exception safety, no side effects
template <class T>
BOOST_DEDUCED_TYPENAME T::iterator_pair
hash_table<T>::equal_range(key_type const& k) const
{
if(!this->size_)
return iterator_pair(this->end(), this->end());
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
node_ptr it = find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(it)) {
iterator_base first(iterator_base(bucket, it));
iterator_base second(first);
second.increment_bucket(node::next_group(second.node_));
return iterator_pair(first, second);
}
else {
return iterator_pair(this->end(), this->end());
}
}
////////////////////////////////////////////////////////////////////////////
// Erase methods
template <class T>
void hash_table<T>::clear()
{
if(!this->size_) return;
bucket_ptr end = this->get_bucket(this->bucket_count_);
for(bucket_ptr begin = this->buckets_; begin != end; ++begin) {
this->clear_bucket(begin);
}
this->size_ = 0;
this->cached_begin_bucket_ = end;
}
template <class T>
inline std::size_t hash_table<T>::erase_group(
node_ptr* it, bucket_ptr bucket)
{
node_ptr pos = *it;
node_ptr end = node::next_group(pos);
*it = end;
std::size_t count = this->delete_nodes(pos, end);
this->size_ -= count;
this->recompute_begin_bucket(bucket);
return count;
}
template <class T>
std::size_t hash_table<T>::erase_key(key_type const& k)
{
if(!this->size_) return 0;
// No side effects in initial section
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
node_ptr* it = this->find_for_erase(bucket, k);
// No throw.
return *it ? this->erase_group(it, bucket) : 0;
}
template <class T>
void hash_table<T>::erase(iterator_base r)
{
BOOST_ASSERT(r.node_);
--this->size_;
node::unlink_node(*r.bucket_, r.node_);
this->delete_node(r.node_);
// r has been invalidated but its bucket is still valid
this->recompute_begin_bucket(r.bucket_);
}
template <class T>
BOOST_DEDUCED_TYPENAME T::iterator_base
hash_table<T>::erase_return_iterator(iterator_base r)
{
BOOST_ASSERT(r.node_);
iterator_base next = r;
next.increment();
--this->size_;
node::unlink_node(*r.bucket_, r.node_);
this->delete_node(r.node_);
// r has been invalidated but its bucket is still valid
this->recompute_begin_bucket(r.bucket_, next.bucket_);
return next;
}
template <class T>
BOOST_DEDUCED_TYPENAME T::iterator_base
hash_table<T>::erase_range(
iterator_base r1, iterator_base r2)
{
if(r1 != r2)
{
BOOST_ASSERT(r1.node_);
if (r1.bucket_ == r2.bucket_) {
node::unlink_nodes(*r1.bucket_, r1.node_, r2.node_);
this->size_ -= this->delete_nodes(r1.node_, r2.node_);
// No need to call recompute_begin_bucket because
// the nodes are only deleted from one bucket, which
// still contains r2 after the erase.
BOOST_ASSERT(r1.bucket_->next_);
}
else {
bucket_ptr end_bucket = r2.node_ ?
r2.bucket_ : this->get_bucket(this->bucket_count_);
BOOST_ASSERT(r1.bucket_ < end_bucket);
node::unlink_nodes(*r1.bucket_, r1.node_, node_ptr());
this->size_ -= this->delete_nodes(r1.node_, node_ptr());
bucket_ptr i = r1.bucket_;
for(++i; i != end_bucket; ++i) {
this->size_ -= this->delete_nodes(i->next_, node_ptr());
i->next_ = node_ptr();
}
if(r2.node_) {
node_ptr first = r2.bucket_->next_;
node::unlink_nodes(*r2.bucket_, r2.node_);
this->size_ -= this->delete_nodes(first, r2.node_);
}
// r1 has been invalidated but its bucket is still
// valid.
this->recompute_begin_bucket(r1.bucket_, end_bucket);
}
}
return r2;
}
template <class T>
BOOST_DEDUCED_TYPENAME hash_table<T>::iterator_base
hash_table<T>::emplace_empty_impl_with_node(
node_constructor& a, std::size_t size)
{
key_type const& k = get_key(a.value());
std::size_t hash_value = this->hash_function()(k);
if(this->buckets_) this->reserve_for_insert(size);
else this->create_for_insert(size);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr n = a.release();
node::add_to_bucket(n, *bucket);
++this->size_;
this->cached_begin_bucket_ = bucket;
return iterator_base(bucket, n);
}
}}
#endif
+513
View File
@@ -0,0 +1,513 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2010 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)
#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#include <boost/unordered/detail/table.hpp>
#include <boost/unordered/detail/extract_key.hpp>
namespace boost { namespace unordered_detail {
template <class T>
class hash_unique_table : public T::table
{
public:
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::value_allocator value_allocator;
typedef BOOST_DEDUCED_TYPENAME T::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME T::table table;
typedef BOOST_DEDUCED_TYPENAME T::node_constructor node_constructor;
typedef BOOST_DEDUCED_TYPENAME T::node node;
typedef BOOST_DEDUCED_TYPENAME T::node_ptr node_ptr;
typedef BOOST_DEDUCED_TYPENAME T::bucket_ptr bucket_ptr;
typedef BOOST_DEDUCED_TYPENAME T::iterator_base iterator_base;
typedef BOOST_DEDUCED_TYPENAME T::extractor extractor;
typedef std::pair<iterator_base, bool> emplace_return;
// Constructors
hash_unique_table(std::size_t n, hasher const& hf, key_equal const& eq,
value_allocator const& a)
: table(n, hf, eq, a) {}
hash_unique_table(hash_unique_table const& x)
: table(x, x.node_alloc()) {}
hash_unique_table(hash_unique_table const& x, value_allocator const& a)
: table(x, a) {}
hash_unique_table(hash_unique_table& x, move_tag m)
: table(x, m) {}
hash_unique_table(hash_unique_table& x, value_allocator const& a,
move_tag m)
: table(x, a, m) {}
~hash_unique_table() {}
// Insert methods
emplace_return emplace_impl_with_node(node_constructor& a);
value_type& operator[](key_type const& k);
// equals
bool equals(hash_unique_table const&) const;
node_ptr add_node(node_constructor& a, bucket_ptr bucket);
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args>
emplace_return emplace(Args&&... args);
template<class... Args>
emplace_return emplace_impl(key_type const& k, Args&&... args);
template<class... Args>
emplace_return emplace_impl(no_key, Args&&... args);
template<class... Args>
emplace_return emplace_empty_impl(Args&&... args);
#else
#define BOOST_UNORDERED_INSERT_IMPL(z, n, _) \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
emplace_return emplace( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
emplace_return emplace_impl(key_type const& k, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
emplace_return emplace_impl(no_key, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n)); \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, n)> \
emplace_return emplace_empty_impl( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, n));
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)
#undef BOOST_UNORDERED_INSERT_IMPL
#endif
// if hash function throws, or inserting > 1 element, basic exception
// safety strong otherwise
template <class InputIt>
void insert_range(InputIt i, InputIt j);
template <class InputIt>
void insert_range_impl(key_type const&, InputIt i, InputIt j);
template <class InputIt>
void insert_range_impl2(node_constructor&, key_type const&, InputIt i, InputIt j);
template <class InputIt>
void insert_range_impl(no_key, InputIt i, InputIt j);
};
template <class H, class P, class A>
struct set : public types<
BOOST_DEDUCED_TYPENAME A::value_type,
BOOST_DEDUCED_TYPENAME A::value_type,
H, P, A,
set_extractor<BOOST_DEDUCED_TYPENAME A::value_type>,
ungrouped>
{
typedef hash_unique_table<set<H, P, A> > impl;
typedef hash_table<set<H, P, A> > table;
};
template <class K, class H, class P, class A>
struct map : public types<
K, BOOST_DEDUCED_TYPENAME A::value_type,
H, P, A,
map_extractor<K, BOOST_DEDUCED_TYPENAME A::value_type>,
ungrouped>
{
typedef hash_unique_table<map<K, H, P, A> > impl;
typedef hash_table<map<K, H, P, A> > table;
};
////////////////////////////////////////////////////////////////////////////
// Equality
template <class T>
bool hash_unique_table<T>
::equals(hash_unique_table<T> const& other) const
{
if(this->size_ != other.size_) return false;
if(!this->size_) return true;
bucket_ptr end = this->get_bucket(this->bucket_count_);
for(bucket_ptr i = this->cached_begin_bucket_; i != end; ++i)
{
node_ptr it1 = i->next_;
while(BOOST_UNORDERED_BORLAND_BOOL(it1))
{
node_ptr it2 = other.find_iterator(this->get_key_from_ptr(it1));
if(!BOOST_UNORDERED_BORLAND_BOOL(it2)) return false;
if(!extractor::compare_mapped(
node::get_value(it1), node::get_value(it2)))
return false;
it1 = it1->next_;
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////
// A convenience method for adding nodes.
template <class T>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::node_ptr
hash_unique_table<T>::add_node(node_constructor& a,
bucket_ptr bucket)
{
node_ptr n = a.release();
node::add_to_bucket(n, *bucket);
++this->size_;
if(bucket < this->cached_begin_bucket_)
this->cached_begin_bucket_ = bucket;
return n;
}
////////////////////////////////////////////////////////////////////////////
// Insert methods
// if hash function throws, basic exception safety
// strong otherwise
template <class T>
BOOST_DEDUCED_TYPENAME hash_unique_table<T>::value_type&
hash_unique_table<T>::operator[](key_type const& k)
{
typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
if(!this->buckets_) {
node_constructor a(*this);
a.construct_pair(k, (mapped_type*) 0);
return *this->emplace_empty_impl_with_node(a, 1);
}
node_ptr pos = this->find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
return node::get_value(pos);
}
else {
// Side effects only in this block.
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(*this);
a.construct_pair(k, (mapped_type*) 0);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
return node::get_value(add_node(a, bucket));
}
}
template <class T>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace_impl_with_node(node_constructor& a)
{
// No side effects in this initial code
key_type const& k = this->get_key(a.value());
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr pos = this->find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
// Found an existing key, return it (no throw).
return emplace_return(iterator_base(bucket, pos), false);
} else {
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
return emplace_return(
iterator_base(bucket, add_node(a, bucket)),
true);
}
}
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class T>
template<class... Args>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace_impl(key_type const& k,
Args&&... args)
{
// No side effects in this initial code
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr pos = this->find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
// Found an existing key, return it (no throw).
return emplace_return(iterator_base(bucket, pos), false);
} else {
// Doesn't already exist, add to bucket.
// Side effects only in this block.
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
return emplace_return(
iterator_base(bucket, add_node(a, bucket)),
true);
}
}
template <class T>
template<class... Args>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace_impl(no_key, Args&&... args)
{
// Construct the node regardless - in order to get the key.
// It will be discarded if it isn't used
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
return emplace_impl_with_node(a);
}
template <class T>
template<class... Args>
inline BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace_empty_impl(Args&&... args)
{
node_constructor a(*this);
a.construct(std::forward<Args>(args)...);
return emplace_return(this->emplace_empty_impl_with_node(a, 1), true);
}
#else
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
inline BOOST_DEDUCED_TYPENAME \
hash_unique_table<T>::emplace_return \
hash_unique_table<T>::emplace_impl( \
key_type const& k, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
std::size_t hash_value = this->hash_function()(k); \
bucket_ptr bucket \
= this->bucket_ptr_from_hash(hash_value); \
node_ptr pos = this->find_iterator(bucket, k); \
\
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) { \
return emplace_return(iterator_base(bucket, pos), false); \
} else { \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
\
if(this->reserve_for_insert(this->size_ + 1)) \
bucket = this->bucket_ptr_from_hash(hash_value); \
\
return emplace_return(iterator_base(bucket, \
add_node(a, bucket)), true); \
} \
} \
\
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
inline BOOST_DEDUCED_TYPENAME \
hash_unique_table<T>::emplace_return \
hash_unique_table<T>:: \
emplace_impl(no_key, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
return emplace_impl_with_node(a); \
} \
\
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
inline BOOST_DEDUCED_TYPENAME \
hash_unique_table<T>::emplace_return \
hash_unique_table<T>:: \
emplace_empty_impl( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
node_constructor a(*this); \
a.construct(BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
return emplace_return(this->emplace_empty_impl_with_node(a, 1), true); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)
#undef BOOST_UNORDERED_INSERT_IMPL
#endif
#if defined(BOOST_UNORDERED_STD_FORWARD)
// Emplace (unique keys)
// (I'm using an overloaded emplace for both 'insert' and 'emplace')
// if hash function throws, basic exception safety
// strong otherwise
template <class T>
template<class... Args>
BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace(Args&&... args)
{
return this->size_ ?
emplace_impl(
extractor::extract(std::forward<Args>(args)...),
std::forward<Args>(args)...) :
emplace_empty_impl(std::forward<Args>(args)...);
}
#else
template <class T>
template <class Arg0>
BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return
hash_unique_table<T>::emplace(Arg0 const& arg0)
{
return this->size_ ?
emplace_impl(extractor::extract(arg0), arg0) :
emplace_empty_impl(arg0);
}
#define BOOST_UNORDERED_INSERT_IMPL(z, num_params, _) \
template <class T> \
template <BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params)> \
BOOST_DEDUCED_TYPENAME hash_unique_table<T>::emplace_return \
hash_unique_table<T>::emplace( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
return this->size_ ? \
emplace_impl(extractor::extract(arg0, arg1), \
BOOST_UNORDERED_CALL_PARAMS(z, num_params)) : \
emplace_empty_impl( \
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
}
BOOST_PP_REPEAT_FROM_TO(2, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_INSERT_IMPL, _)
#undef BOOST_UNORDERED_INSERT_IMPL
#endif
////////////////////////////////////////////////////////////////////////////
// Insert range methods
template <class T>
template <class InputIt>
inline void hash_unique_table<T>::insert_range_impl2(
node_constructor& a, key_type const& k, InputIt i, InputIt j)
{
// No side effects in this initial code
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
node_ptr pos = this->find_iterator(bucket, k);
if (!BOOST_UNORDERED_BORLAND_BOOL(pos)) {
// Doesn't already exist, add to bucket.
// Side effects only in this block.
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
a.construct(*i);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->size_ + 1 >= this->max_load_) {
this->reserve_for_insert(this->size_ + insert_size(i, j));
bucket = this->bucket_ptr_from_hash(hash_value);
}
// Nothing after this point can throw.
add_node(a, bucket);
}
}
template <class T>
template <class InputIt>
inline void hash_unique_table<T>::insert_range_impl(
key_type const&, InputIt i, InputIt j)
{
node_constructor a(*this);
if(!this->size_) {
a.construct(*i);
this->emplace_empty_impl_with_node(a, 1);
++i;
if(i == j) return;
}
do {
// 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.
//
// TODO: Might be worth storing the value_type instead of the key
// here. Could be more efficient if '*i' is expensive. Could be
// less efficient if copying the full value_type is expensive.
insert_range_impl2(a, extractor::extract(*i), i, j);
} while(++i != j);
}
template <class T>
template <class InputIt>
inline void hash_unique_table<T>::insert_range_impl(
no_key, InputIt i, InputIt j)
{
node_constructor a(*this);
if(!this->size_) {
a.construct(*i);
this->emplace_empty_impl_with_node(a, 1);
++i;
if(i == j) return;
}
do {
// No side effects in this initial code
a.construct(*i);
emplace_impl_with_node(a);
} while(++i != j);
}
// if hash function throws, or inserting > 1 element, basic exception safety
// strong otherwise
template <class T>
template <class InputIt>
void hash_unique_table<T>::insert_range(InputIt i, InputIt j)
{
if(i != j)
return insert_range_impl(extractor::extract(*i), i, j);
}
}}
#endif
+331
View File
@@ -0,0 +1,331 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-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)
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#include <cstddef>
#include <utility>
#include <algorithm>
#include <boost/limits.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/unordered/detail/fwd.hpp>
namespace boost { namespace unordered_detail {
////////////////////////////////////////////////////////////////////////////
// convert double to std::size_t
inline std::size_t double_to_size_t(double f)
{
return f >= static_cast<double>(
(std::numeric_limits<std::size_t>::max)()) ?
(std::numeric_limits<std::size_t>::max)() :
static_cast<std::size_t>(f);
}
////////////////////////////////////////////////////////////////////////////
// primes
#define BOOST_UNORDERED_PRIMES \
(5ul)(11ul)(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) \
(1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \
(50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
(1610612741ul)(3221225473ul)(4294967291ul)
template<class T> struct prime_list_template
{
static std::size_t const value[];
#if !defined(SUNPRO_CC)
static std::ptrdiff_t const length;
#else
static std::ptrdiff_t const length
= BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
#endif
};
template<class T>
std::size_t const prime_list_template<T>::value[] = {
BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)
};
#if !defined(SUNPRO_CC)
template<class T>
std::ptrdiff_t const prime_list_template<T>::length
= BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
#endif
#undef BOOST_UNORDERED_PRIMES
typedef prime_list_template<std::size_t> prime_list;
// no throw
inline std::size_t next_prime(std::size_t num) {
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin +
prime_list::length;
std::size_t const* bound =
std::lower_bound(prime_list_begin, prime_list_end, num);
if(bound == prime_list_end)
bound--;
return *bound;
}
// no throw
inline std::size_t prev_prime(std::size_t num) {
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin +
prime_list::length;
std::size_t const* bound =
std::upper_bound(prime_list_begin,prime_list_end, num);
if(bound != prime_list_begin)
bound--;
return *bound;
}
////////////////////////////////////////////////////////////////////////////
// pair_cast - because some libraries don't have the full pair constructors.
template <class Dst1, class Dst2, class Src1, class Src2>
inline std::pair<Dst1, Dst2> pair_cast(std::pair<Src1, Src2> const& x)
{
return std::pair<Dst1, Dst2>(Dst1(x.first), Dst2(x.second));
}
////////////////////////////////////////////////////////////////////////////
// insert_size/initial_size
#if !defined(BOOST_NO_STD_DISTANCE)
using ::std::distance;
#else
template <class ForwardIterator>
inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
std::size_t x;
std::distance(i, j, x);
return x;
}
#endif
template <class I>
inline std::size_t insert_size(I i, I j, boost::forward_traversal_tag)
{
return std::distance(i, j);
}
template <class I>
inline std::size_t insert_size(I, I, boost::incrementable_traversal_tag)
{
return 1;
}
template <class I>
inline std::size_t insert_size(I i, I j)
{
BOOST_DEDUCED_TYPENAME boost::iterator_traversal<I>::type
iterator_traversal_tag;
return insert_size(i, j, iterator_traversal_tag);
}
template <class I>
inline std::size_t initial_size(I i, I j,
std::size_t num_buckets = boost::unordered_detail::default_bucket_count)
{
return (std::max)(static_cast<std::size_t>(insert_size(i, j)) + 1,
num_buckets);
}
////////////////////////////////////////////////////////////////////////////
// Node Constructors
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class T, class... Args>
inline void construct_impl(T*, void* address, Args&&... args)
{
new(address) T(std::forward<Args>(args)...);
}
#if defined(BOOST_UNORDERED_CPP0X_PAIR)
template <class First, class Second, class Key, class Arg0, class... Args>
inline void construct_impl(std::pair<First, Second>*, void* address,
Key&& k, Arg0&& arg0, Args&&... args)
)
{
new(address) std::pair<First, Second>(k,
Second(arg0, std::forward<Args>(args)...);
}
#endif
#else
#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
template < \
class T, \
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
inline void construct_impl( \
T*, void* address, \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
) \
{ \
new(address) T( \
BOOST_UNORDERED_CALL_PARAMS(z, num_params)); \
} \
\
template <class First, class Second, class Key, \
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
inline void construct_impl( \
std::pair<First, Second>*, void* address, \
Key const& k, BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params)) \
{ \
new(address) std::pair<First, Second>(k, \
Second(BOOST_UNORDERED_CALL_PARAMS(z, num_params))); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT_IMPL, _)
#undef BOOST_UNORDERED_CONSTRUCT_IMPL
#endif
// hash_node_constructor
//
// Used to construct nodes in an exception safe manner.
template <class Alloc, class Grouped>
class hash_node_constructor
{
typedef hash_buckets<Alloc, Grouped> buckets;
typedef BOOST_DEDUCED_TYPENAME buckets::node node;
typedef BOOST_DEDUCED_TYPENAME buckets::real_node_ptr real_node_ptr;
typedef BOOST_DEDUCED_TYPENAME buckets::value_type value_type;
buckets& buckets_;
real_node_ptr node_;
bool node_constructed_;
bool value_constructed_;
public:
hash_node_constructor(buckets& m) :
buckets_(m),
node_(),
node_constructed_(false),
value_constructed_(false)
{
}
~hash_node_constructor();
void construct_preamble();
#if defined(BOOST_UNORDERED_STD_FORWARD)
template <class... Args>
void construct(Args&&... args)
{
construct_preamble();
construct_impl((value_type*) 0, node_->address(),
std::forward<Args>(args)...);
value_constructed_ = true;
}
#else
#define BOOST_UNORDERED_CONSTRUCT(z, num_params, _) \
template < \
BOOST_UNORDERED_TEMPLATE_ARGS(z, num_params) \
> \
void construct( \
BOOST_UNORDERED_FUNCTION_PARAMS(z, num_params) \
) \
{ \
construct_preamble(); \
construct_impl( \
(value_type*) 0, node_->address(), \
BOOST_UNORDERED_CALL_PARAMS(z, num_params) \
); \
value_constructed_ = true; \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT,
BOOST_UNORDERED_CONSTRUCT, _)
#undef BOOST_UNORDERED_CONSTRUCT
#endif
template <class K, class M>
void construct_pair(K const& k, M*)
{
construct_preamble();
new(node_->address()) value_type(k, M());
value_constructed_ = true;
}
value_type& value() const
{
BOOST_ASSERT(node_);
return node_->value();
}
// no throw
BOOST_DEDUCED_TYPENAME buckets::node_ptr release()
{
real_node_ptr p = node_;
node_ = real_node_ptr();
// node_ptr cast
return buckets_.bucket_alloc().address(*p);
}
private:
hash_node_constructor(hash_node_constructor const&);
hash_node_constructor& operator=(hash_node_constructor const&);
};
// hash_node_constructor
template <class Alloc, class Grouped>
inline hash_node_constructor<Alloc, Grouped>::~hash_node_constructor()
{
if (node_) {
if (value_constructed_) {
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy { hash_node<Alloc, Grouped> x; };
#endif
boost::unordered_detail::destroy(&node_->value());
}
if (node_constructed_)
buckets_.node_alloc().destroy(node_);
buckets_.node_alloc().deallocate(node_, 1);
}
}
template <class Alloc, class Grouped>
inline void hash_node_constructor<Alloc, Grouped>::construct_preamble()
{
if(!node_) {
node_constructed_ = false;
value_constructed_ = false;
node_ = buckets_.node_alloc().allocate(1);
buckets_.node_alloc().construct(node_, node());
node_constructed_ = true;
}
else {
BOOST_ASSERT(node_constructed_ && value_constructed_);
boost::unordered_detail::destroy(&node_->value());
value_constructed_ = false;
}
}
}}
#endif
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
// Copyright (C) 2008 Daniel James.
// Copyright (C) 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)
@@ -17,11 +17,11 @@
namespace boost
{
template <class Key,
template <class K,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class H = 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>
bool operator==(unordered_map<K, T, H, P, A> const&,
@@ -33,11 +33,11 @@ namespace boost
void swap(unordered_map<K, T, H, P, A>&,
unordered_map<K, T, H, P, A>&);
template <class Key,
template <class K,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class H = 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>
bool operator==(unordered_multimap<K, T, H, P, A> const&,
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
// Copyright (C) 2008 Daniel James.
// Copyright (C) 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)
@@ -17,10 +17,10 @@
namespace boost
{
template <class Value,
class Hash = hash<Value>,
class Pred = std::equal_to<Value>,
class Alloc = std::allocator<Value> >
template <class T,
class H = 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>
bool operator==(unordered_set<T, H, P, A> const&,
@@ -32,10 +32,10 @@ namespace boost
void swap(unordered_set<T, H, P, A> &m1,
unordered_set<T, H, P, A> &m2);
template <class Value,
class Hash = hash<Value>,
class Pred = std::equal_to<Value>,
class Alloc = std::allocator<Value> >
template <class T,
class H = 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>
bool operator==(unordered_multiset<T, H, P, A> const&,
-1
View File
@@ -1 +0,0 @@
boost_module(unordered DEPENDS config functional)
-75
View File
@@ -1,75 +0,0 @@
boost_additional_test_dependencies(unordered BOOST_DEPENDS test)
# GCC Compilers
IF(CMAKE_COMPILER_IS_GNUCC)
SET(test_compile_flags "-Wsign-promo -Wunused-parameter")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
# Intel Compiler flags
IF( ${CMAKE_CXX_COMPILER} MATCHES "icpc" )
SET(test_compile_flags "${test_compile_flags} -strict_ansi -cxxlib-icc")
ENDIF( ${CMAKE_CXX_COMPILER} MATCHES "icpc" )
set (swap_compile_flags "${test_compile_flags} -DBOOST_UNORDERED_SWAP_METHOD=2")
#-------------------------------------------------------------------------------
# Unordered Tests
set (unordered_tests
fwd_set_test
fwd_map_test
compile_set
compile_map
link_test_1
link_test_2
simple_tests
equivalent_keys_tests
constructor_tests
copy_tests
move_tests.cpp
assign_tests
insert_tests
insert_stable_tests
unnecessary_copy_tests
erase_tests
erase_equiv_tests
find_tests
at_tests
bucket_tests
load_factor_tests
rehash_tests
equality_tests
)
#-- Create an executable test for each source
foreach(test ${unordered_tests})
boost_test_run(${test} "unordered/${test}.cpp"
COMPILE_FLAGS ${test_compile_flags}
DEPENDS boost_unit_test_framework)
endforeach(test ${unordered_tests})
#-- run the swap test
boost_test_run(swap_tests
COMPILE_FLAGS ${swap_compile_flags}
DEPENDS boost_unit_test_framework)
#-------------------------------------------------------------------------------
# Exception Tests
set (exception_tests
constructor_exception_tests
copy_exception_tests
assign_exception_tests
insert_exception_tests
erase_exception_tests
rehash_exception_tests
)
#-- Create an executable test for each source
foreach(test ${exception_tests})
boost_test_run(${test} "exception/${test}.cpp"
COMPILE_FLAGS ${test_compile_flags}
DEPENDS boost_unit_test_framework)
endforeach(test ${unordered_tests})
#-- run the swap test
boost_test_run(swap_swap_exception_tests
COMPILE_FLAGS ${swap_compile_flags}
DEPENDS boost_unit_test_framework)
+2
View File
@@ -3,5 +3,7 @@
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import testing ;
build-project unordered ;
build-project exception ;
+9 -2
View File
@@ -10,8 +10,15 @@ alias framework : ;
project unordered-test/exception-tests
: requirements
<toolset>intel-linux:"<cxxflags>-strict_ansi -cxxlib-icc"
<toolset>gcc:<cxxflags>"-Wsign-promo -Wunused-parameter"
<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
;
test-suite unordered-exception
+19 -7
View File
@@ -1,12 +1,18 @@
// Copyright 2006-2008 Daniel James.
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t seed(12847);
template <class T>
@@ -18,7 +24,8 @@ struct self_assign_base : public test::exception_base
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const { x = x; }
void check(T const& x) const { test::check_equivalent_keys(x); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{ test::check_equivalent_keys(x); }
};
template <class T>
@@ -40,15 +47,20 @@ struct assign_base : public test::exception_base
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)
: x_values(count1), y_values(count2),
x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2), allocator_type(tag2)) {}
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2) :
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))
{}
typedef T data_type;
T init() const { return T(x); }
void run(T& x1) const { x1 = y; }
void check(T const& x1) const { test::check_equivalent_keys(x1); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{ test::check_equivalent_keys(x1); }
};
template <class T>
+48 -7
View File
@@ -1,12 +1,16 @@
// Copyright 2006-2008 Daniel James.
// 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 "./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);
struct objects
@@ -22,6 +26,7 @@ struct construct_test1 : public objects, test::exception_base
{
void run() const {
T x;
avoid_unused_warning(x);
}
};
@@ -30,6 +35,7 @@ struct construct_test2 : public objects, test::exception_base
{
void run() const {
T x(300);
avoid_unused_warning(x);
}
};
@@ -38,6 +44,7 @@ struct construct_test3 : public objects, test::exception_base
{
void run() const {
T x(0, hash);
avoid_unused_warning(x);
}
};
@@ -46,6 +53,7 @@ struct construct_test4 : public objects, test::exception_base
{
void run() const {
T x(0, hash, equal_to);
avoid_unused_warning(x);
}
};
@@ -54,6 +62,7 @@ struct construct_test5 : public objects, test::exception_base
{
void run() const {
T x(50, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
@@ -62,6 +71,7 @@ struct construct_test6 : public objects, test::exception_base
{
void run() const {
T x(allocator);
avoid_unused_warning(x);
}
};
@@ -79,6 +89,7 @@ struct range_construct_test1 : public range<T>, objects
{
void run() const {
T x(this->values.begin(), this->values.end());
avoid_unused_warning(x);
}
};
@@ -87,6 +98,7 @@ struct range_construct_test2 : public range<T>, objects
{
void run() const {
T x(this->values.begin(), this->values.end(), 0);
avoid_unused_warning(x);
}
};
@@ -95,6 +107,7 @@ struct range_construct_test3 : public range<T>, objects
{
void run() const {
T x(this->values.begin(), this->values.end(), 0, hash);
avoid_unused_warning(x);
}
};
@@ -103,6 +116,7 @@ struct range_construct_test4 : public range<T>, objects
{
void run() const {
T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
avoid_unused_warning(x);
}
};
@@ -114,7 +128,9 @@ struct range_construct_test5 : public range<T>, objects
range_construct_test5() : range<T>(60) {}
void run() const {
T x(this->values.begin(), this->values.end(), 0, hash, equal_to, allocator);
T x(this->values.begin(), this->values.end(), 0,
hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
@@ -124,14 +140,39 @@ struct input_range_construct_test : public range<T>, objects
input_range_construct_test() : range<T>(60) {}
void run() const {
T x(test::input_iterator(this->values.begin()),
test::input_iterator(this->values.end()),
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
begin = this->values.begin(), end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end),
0, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
template <class T>
struct copy_range_construct_test : public range<T>, objects
{
copy_range_construct_test() : range<T>(60) {}
void run() const {
T x(test::copy_iterator(this->values.begin()),
test::copy_iterator(this->values.end()),
0, hash, equal_to, allocator);
avoid_unused_warning(x);
}
};
RUN_EXCEPTION_TESTS(
(construct_test1)(construct_test2)(construct_test3)(construct_test4)(construct_test5)(construct_test6)
(range_construct_test1)(range_construct_test2)(range_construct_test3)(range_construct_test4)(range_construct_test5)
(input_range_construct_test),
(construct_test1)
(construct_test2)
(construct_test3)
(construct_test4)
(construct_test5)
(construct_test6)
(range_construct_test1)
(range_construct_test2)
(range_construct_test3)
(range_construct_test4)
(range_construct_test5)
(input_range_construct_test)
(copy_range_construct_test),
CONTAINER_SEQ)
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
+9 -1
View File
@@ -1,11 +1,15 @@
// Copyright 2006-2008 Daniel James.
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
template <typename T> inline void avoid_unused_warning(T const&) {}
test::seed_t seed(73041);
template <class T>
@@ -15,6 +19,7 @@ struct copy_test1 : public test::exception_base
void run() const {
T y(x);
avoid_unused_warning(y);
}
};
@@ -28,6 +33,7 @@ struct copy_test2 : public test::exception_base
void run() const {
T y(x);
avoid_unused_warning(y);
}
};
@@ -41,6 +47,7 @@ struct copy_test3 : public test::exception_base
void run() const {
T y(x);
avoid_unused_warning(y);
}
};
@@ -55,6 +62,7 @@ struct copy_with_allocator_test : public test::exception_base
void run() const {
T y(x, allocator);
avoid_unused_warning(y);
}
};
+7 -4
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
@@ -22,10 +24,10 @@ struct erase_test_base : public test::exception_base
return T(values.begin(), values.end());
}
void check(T const& x) const {
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
std::string scope(test::scope);
BOOST_CHECK(scope.find("hash::") != std::string::npos ||
BOOST_TEST(scope.find("hash::") != std::string::npos ||
scope.find("equal_to::") != std::string::npos ||
scope == "operator==(object, object)");
@@ -38,7 +40,8 @@ struct erase_by_key_test1 : public erase_test_base<T>
{
void run(T& x) const
{
typedef BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator iterator;
typedef BOOST_DEDUCED_TYPENAME
test::random_values<T>::const_iterator iterator;
for(iterator it = this->values.begin(), end = this->values.end();
it != end; ++it)
+41 -30
View File
@@ -1,14 +1,15 @@
// Copyright 2006-2008 Daniel James.
// 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 "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/input_iterator.hpp"
#include <boost/utility.hpp>
#include <cmath>
@@ -27,16 +28,18 @@ struct insert_test_base : public test::exception_base
return T();
}
void check(T const& x, strong_type const& strong) const {
void check BOOST_PREVENT_MACRO_SUBSTITUTION(
T const& x, strong_type const& strong) const
{
std::string scope(test::scope);
if(scope.find("hash::operator()") == std::string::npos)
strong.test(x);
strong.test(x, test::exception::detail::tracker.count_allocations);
test::check_equivalent_keys(x);
}
};
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class T>
struct emplace_test1 : public insert_test_base<T>
@@ -45,9 +48,10 @@ struct emplace_test1 : public insert_test_base<T>
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = this->values.begin(), end = this->values.end(); it != end; ++it)
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.emplace(*it);
}
}
@@ -62,9 +66,10 @@ struct insert_test1 : public insert_test_base<T>
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = this->values.begin(), end = this->values.end(); it != end; ++it)
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.insert(*it);
}
}
@@ -77,9 +82,10 @@ struct insert_test2 : public insert_test_base<T>
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = this->values.begin(), end = this->values.end(); it != end; ++it)
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.insert(x.begin(), *it);
}
}
@@ -92,7 +98,7 @@ struct insert_test3 : public insert_test_base<T>
x.insert(this->values.begin(), this->values.end());
}
void check(T const& x) const {
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
test::check_equivalent_keys(x);
}
};
@@ -104,9 +110,10 @@ struct insert_test4 : public insert_test_base<T>
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = this->values.begin(), end = this->values.end(); it != end; ++it)
it = this->values.begin(), end = this->values.end();
it != end; ++it)
{
strong.store(x);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.insert(it, boost::next(it));
}
}
@@ -128,10 +135,10 @@ struct insert_test_rehash1 : public insert_test_base<T>
size_type bucket_count = x.bucket_count();
size_type initial_elements = static_cast<size_type>(
ceil(bucket_count * (double) x.max_load_factor()) - 1);
BOOST_REQUIRE(initial_elements < this->values.size());
BOOST_TEST(initial_elements < this->values.size());
x.insert(this->values.begin(),
boost::next(this->values.begin(), initial_elements));
BOOST_REQUIRE(bucket_count == x.bucket_count());
BOOST_TEST(bucket_count == x.bucket_count());
return x;
}
@@ -141,16 +148,17 @@ struct insert_test_rehash1 : public insert_test_base<T>
BOOST_DEDUCED_TYPENAME T::const_iterator pos = x.cbegin();
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = boost::next(this->values.begin(), x.size()), end = this->values.end();
it = boost::next(this->values.begin(), x.size()),
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x);
strong.store(x, test::exception::detail::tracker.count_allocations);
pos = x.insert(pos, *it);
}
// This isn't actually a failure, but it means the test isn't doing its
// job.
BOOST_REQUIRE(x.bucket_count() != bucket_count);
BOOST_TEST(x.bucket_count() != bucket_count);
}
};
@@ -164,23 +172,25 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
int count = 0;
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
it = boost::next(this->values.begin(), x.size()), end = this->values.end();
it = boost::next(this->values.begin(), x.size()),
end = this->values.end();
it != end && count < 10; ++it, ++count)
{
strong.store(x);
strong.store(x, test::exception::detail::tracker.count_allocations);
x.insert(*it);
}
// This isn't actually a failure, but it means the test isn't doing its
// job.
BOOST_REQUIRE(x.bucket_count() != bucket_count);
BOOST_TEST(x.bucket_count() != bucket_count);
}
};
template <class T>
struct insert_test_rehash3 : public insert_test_base<T>
{
BOOST_DEDUCED_TYPENAME T::size_type mutable rehash_bucket_count, original_bucket_count;
BOOST_DEDUCED_TYPENAME T::size_type mutable
rehash_bucket_count, original_bucket_count;
insert_test_rehash3() : insert_test_base<T>(1000) {}
@@ -195,12 +205,13 @@ struct insert_test_rehash3 : public insert_test_base<T>
rehash_bucket_count = static_cast<size_type>(
ceil(original_bucket_count * (double) x.max_load_factor())) - 1;
size_type initial_elements = rehash_bucket_count - 5;
size_type initial_elements =
rehash_bucket_count > 5 ? rehash_bucket_count - 5 : 1;
BOOST_REQUIRE(initial_elements < this->values.size());
BOOST_TEST(initial_elements < this->values.size());
x.insert(this->values.begin(),
boost::next(this->values.begin(), initial_elements));
BOOST_REQUIRE(original_bucket_count == x.bucket_count());
BOOST_TEST(original_bucket_count == x.bucket_count());
return x;
}
@@ -212,12 +223,12 @@ struct insert_test_rehash3 : public insert_test_base<T>
// This isn't actually a failure, but it means the test isn't doing its
// job.
BOOST_REQUIRE(x.bucket_count() != bucket_count);
BOOST_TEST(x.bucket_count() != bucket_count);
}
void check(T const& x) const {
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
if(x.size() < rehash_bucket_count) {
//BOOST_CHECK(x.bucket_count() == original_bucket_count);
//BOOST_TEST(x.bucket_count() == original_bucket_count);
}
test::check_equivalent_keys(x);
}
@@ -227,7 +238,7 @@ 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_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
#define ALL_TESTS (emplace_test1)BASIC_TESTS
#else
#define ALL_TESTS BASIC_TESTS
+9 -3
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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 "./containers.hpp"
#include <string>
#include "../helpers/random_values.hpp"
@@ -18,7 +20,9 @@ struct rehash_test_base : public test::exception_base
{
test::random_values<T> values;
unsigned int n;
rehash_test_base(unsigned int count = 100, unsigned int n = 0) : values(count), n(n) {}
rehash_test_base(unsigned int count = 100, unsigned int n = 0)
: values(count), n(n)
{}
typedef T data_type;
typedef test::strong<T> strong_type;
@@ -28,7 +32,9 @@ struct rehash_test_base : public test::exception_base
return x;
}
void check(T const& x, strong_type const& strong) const {
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x,
strong_type const& strong) const
{
std::string scope(test::scope);
if(scope.find("hash::operator()") == std::string::npos &&
+11 -5
View File
@@ -1,12 +1,18 @@
// Copyright 2006-2008 Daniel James.
// 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 "./containers.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/invariants.hpp"
#if defined(BOOST_MSVC)
#pragma warning(disable:4512) // assignment operator could not be generated
#endif
test::seed_t seed(9387);
template <class T>
@@ -18,11 +24,11 @@ struct self_swap_base : public test::exception_base
typedef T data_type;
T init() const { return T(values.begin(), values.end()); }
void run(T& x) const { x.swap(x); }
void check(T const& x) const {
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const {
std::string scope(test::scope);
#if BOOST_UNORDERED_SWAP_METHOD != 2
BOOST_CHECK(
BOOST_TEST(
scope == "hash::operator(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::operator(equal_to)" ||
@@ -73,11 +79,11 @@ struct swap_base : public test::exception_base
d.x.swap(d.y);
} catch (std::runtime_error) {}
}
void check(data_type const& d) const {
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const {
std::string scope(test::scope);
#if BOOST_UNORDERED_SWAP_METHOD != 2
BOOST_CHECK(
BOOST_TEST(
scope == "hash::operator(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::operator(equal_to)" ||
+3 -3
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -58,8 +58,8 @@ namespace test
return (std::numeric_limits<size_type>::max)();
}
bool operator==(malloc_allocator const& x) const { return true; }
bool operator!=(malloc_allocator const& x) const { return false; }
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) {
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-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)
+15 -1
View File
@@ -1,11 +1,13 @@
// Copyright 2008 Daniel James.
// Copyright 2008-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD)
#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
#include <iostream>
namespace test {
struct object_count {
int instances;
@@ -36,6 +38,18 @@ namespace test {
bool operator!=(object_count const& x) const {
return !(*this == x);
}
friend std::ostream& operator<<(std::ostream& out,
object_count const& c)
{
out
<< "[instances: "
<< c.instances
<< ", constructions: "
<< c.constructions
<< "]";
return out;
}
};
template <class T>
+7 -3
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-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)
@@ -21,12 +21,16 @@ namespace test
}
template <class T>
bool equivalent_impl(boost::hash<T> const&, boost::hash<T> const&, derived_type) {
bool equivalent_impl(boost::hash<T> const&, boost::hash<T> const&,
derived_type)
{
return true;
}
template <class T>
bool equivalent_impl(std::equal_to<T> const&, std::equal_to<T> const&, derived_type) {
bool equivalent_impl(std::equal_to<T> const&, std::equal_to<T> const&,
derived_type)
{
return true;
}
+57 -64
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -8,64 +8,54 @@
#include "./test.hpp"
#if defined(BOOST_UNORDERED_FULL_TEST)
# define BOOST_TEST_MAIN
# include <boost/test/exception_safety.hpp>
# include <boost/test/unit_test.hpp>
#endif
#include <boost/preprocessor/seq/for_each_product.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/cat.hpp>
#if defined(BOOST_UNORDERED_FULL_TEST)
# define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \
{ \
test_func< type > fixture; \
::test::exception_safety(fixture, BOOST_STRINGIZE(test_func<type>)); \
}
# define UNORDERED_EPOINT_IMPL BOOST_ITEST_EPOINT
#else
# define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \
{ \
test_func< type > fixture; \
::test::lightweight::exception_safety(fixture, BOOST_STRINGIZE(test_func<type>)); \
}
# define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \
{ \
test_func< type > fixture; \
::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \
} \
# define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
#endif
#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 RUN_EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, \
(test_seq)(param_seq)) \
RUN_TESTS() \
#define RUN_EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \
), \
BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product) \
)
#define RUN_EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \
), \
BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product) \
) \
#define UNORDERED_SCOPE(scope_name) \
for(::test::scope_guard unordered_test_guard( \
BOOST_STRINGIZE(scope_name)); \
!unordered_test_guard.dismissed(); \
unordered_test_guard.dismiss())
#define UNORDERED_SCOPE(scope_name) \
for(::test::scope_guard unordered_test_guard( \
BOOST_STRINGIZE(scope_name)); \
!unordered_test_guard.dismissed(); \
unordered_test_guard.dismiss()) \
#define UNORDERED_EPOINT(name) \
if(::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \
}
#define UNORDERED_EPOINT(name) \
if(::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \
} \
#define ENABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true)
#define DISABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false)
#define ENABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT( \
ENABLE_EXCEPTIONS_, __LINE__)(true) \
#define DISABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT( \
ENABLE_EXCEPTIONS_, __LINE__)(false) \
namespace test {
static char const* scope = "";
@@ -126,25 +116,28 @@ namespace test {
template <class T> void test(T const&) const {}
};
data_type init() const { return data_type(); }
void check() const {}
void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
};
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(void (T::*fn)() const, T2 const& obj,
inline void call_ignore_extra_parameters(
void (T::*fn)() const, T2 const& obj,
P1&, P2&)
{
(obj.*fn)();
}
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(void (T::*fn)(P1&) const, T2 const& obj,
inline void call_ignore_extra_parameters(
void (T::*fn)(P1&) const, T2 const& obj,
P1& p1, P2&)
{
(obj.*fn)(p1);
}
template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters(void (T::*fn)(P1&, P2&) const, T2 const& obj,
inline void call_ignore_extra_parameters(
void (T::*fn)(P1&, P2&) const, T2 const& obj,
P1& p1, P2& p2)
{
(obj.*fn)(p1, p2);
@@ -159,6 +152,9 @@ namespace test {
class test_runner
{
Test const& test_;
test_runner(test_runner const&);
test_runner& operator=(test_runner const&);
public:
test_runner(Test const& t) : test_(t) {}
void operator()() const {
@@ -169,25 +165,23 @@ namespace test {
strong.store(x);
try {
ENABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test, BOOST_DEDUCED_TYPENAME Test::data_type, BOOST_DEDUCED_TYPENAME Test::strong_type>(&Test::run, test_, x, strong);
call_ignore_extra_parameters<
Test,
BOOST_DEDUCED_TYPENAME Test::data_type,
BOOST_DEDUCED_TYPENAME Test::strong_type
>(&Test::run, test_, x, strong);
}
catch(...) {
call_ignore_extra_parameters<Test, BOOST_DEDUCED_TYPENAME Test::data_type const, BOOST_DEDUCED_TYPENAME Test::strong_type const>(&Test::check, test_,
constant(x), constant(strong));
call_ignore_extra_parameters<
Test,
BOOST_DEDUCED_TYPENAME Test::data_type const,
BOOST_DEDUCED_TYPENAME Test::strong_type const
>(&Test::check, test_, constant(x), constant(strong));
throw;
}
}
};
#if defined(BOOST_UNORDERED_FULL_TEST)
template <class Test>
void exception_safety(Test const& f, char const* name) {
test_runner<Test> runner(f);
::boost::itest::exception_safety(runner, name);
}
#else
// Quick exception testing based on lightweight test
namespace lightweight {
@@ -237,7 +231,6 @@ namespace test {
} while(!success);
}
}
#endif
}
#endif
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-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)
+5 -3
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -19,13 +19,15 @@ namespace test
}
template <class T>
static key_type const& get_key(std::pair<key_type, T> const& x, char = 0)
static key_type const& get_key(
std::pair<key_type, T> const& x, char = 0)
{
return x.first;
}
template <class T>
static key_type const& get_key(std::pair<key_type const, T> const& x, unsigned char = 0)
static key_type const& get_key(std::pair<key_type const, T> const& x,
unsigned char = 0)
{
return x.first;
}
+142 -12
View File
@@ -1,34 +1,164 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-2010 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_HELPERS_INPUT_ITERATOR_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_INPUT_ITERATOR_HEADER
#include <boost/iterator_adaptors.hpp>
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>
namespace test
{
template <class Iterator>
struct input_iterator_adaptor
: boost::iterator_adaptor<
input_iterator_adaptor<Iterator>, Iterator,
boost::use_default, std::input_iterator_tag>
struct proxy
{
typedef boost::iterator_adaptor<
input_iterator_adaptor<Iterator>, Iterator,
boost::use_default, std::input_iterator_tag> base;
typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type;
explicit input_iterator_adaptor(Iterator it = Iterator())
: base(it) {}
explicit proxy(value_type const& v) : v_(v) {}
proxy(proxy const& x) : v_(x.v_) {}
operator value_type const&() const { return v_; }
value_type v_;
private:
proxy& operator=(proxy const&);
};
template <class Iterator>
input_iterator_adaptor<Iterator> input_iterator(Iterator it)
struct input_iterator_adaptor
: public boost::iterator<
std::input_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator>
>
{
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
input_iterator_adaptor()
: base_() {}
explicit input_iterator_adaptor(Iterator& it)
: base_(&it) {}
proxy<Iterator> operator*() const {
return proxy<Iterator>(**base_);
}
value_type* operator->() const {
return &**base_;
}
input_iterator_adaptor& operator++() {
++*base_; return *this;
}
//input_iterator_adaptor operator++(int) {
//}
bool operator==(input_iterator_adaptor const& x) const {
return *base_ == *x.base_;
}
bool operator!=(input_iterator_adaptor const& x) const {
return *base_ != *x.base_;
}
private:
Iterator* base_;
};
template <class Iterator>
input_iterator_adaptor<Iterator> input_iterator(Iterator& it)
{
return input_iterator_adaptor<Iterator>(it);
}
template <class Iterator>
struct copy_iterator_adaptor
: public boost::iterator<
BOOST_DEDUCED_TYPENAME boost::iterator_category<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator>
>
{
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type
difference_type;
copy_iterator_adaptor()
: base_() {}
explicit copy_iterator_adaptor(Iterator const& it)
: base_(it) {}
value_type operator*() const {
return *base_;
}
value_type* operator->() const {
return &*base_;
}
value_type operator[](difference_type d) {
return base_[d];
}
copy_iterator_adaptor& operator++() {
++base_; return *this;
}
copy_iterator_adaptor operator++(int) {
copy_iterator_adaptor tmp(*this); ++base_; return tmp;
}
copy_iterator_adaptor& operator--() {
--base_; return *this;
}
copy_iterator_adaptor operator--(int) {
copy_iterator_adaptor tmp(*this); --base_; return tmp;
}
copy_iterator_adaptor operator+=(difference_type x) {
base_ += x;
return *this;
}
copy_iterator_adaptor operator-=(difference_type x) {
base_ -= x;
return *this;
}
copy_iterator_adaptor operator+(difference_type n) {
return copy_iterator_adaptor(base_+n);
}
copy_iterator_adaptor operator-(difference_type n) {
return copy_iterator_adaptor(base_-n);
}
friend copy_iterator_adaptor operator+(
difference_type n, copy_iterator_adaptor x) {
return x+n;
}
difference_type operator-(copy_iterator_adaptor const& other) {
return base_-other.base_;
}
bool operator==(copy_iterator_adaptor const& x) const {
return base_ == x.base_;
}
bool operator!=(copy_iterator_adaptor const& x) const {
return base_ != x.base_;
}
bool operator<(copy_iterator_adaptor const& x) const {
return base_ < x.base_;
}
bool operator>(copy_iterator_adaptor const& x) const {
return base_ > x.base_;
}
bool operator<=(copy_iterator_adaptor const& x) const {
return base_ <= x.base_;
}
bool operator>=(copy_iterator_adaptor const& x) const {
return base_ >= x.base_;
}
private:
Iterator base_;
};
template <class Iterator>
copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
{
return copy_iterator_adaptor<Iterator>(it);
}
}
#endif
+14 -7
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -17,7 +17,9 @@
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4127) // conditional expression is constant
#pragma warning(disable:4127) // conditional expression is constant
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data
#endif
namespace test
@@ -29,9 +31,11 @@ namespace test
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>,
test::malloc_allocator<key_type> > found_;
BOOST_DEDUCED_TYPENAME X::const_iterator it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::const_iterator
it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::size_type size = 0;
while(it != end) {
// First test that the current key has not occured before, required
@@ -71,7 +75,8 @@ namespace test
// // Check that the keys are in the correct bucket and are
// // adjacent in the bucket.
// BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
// BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket), lend = x1.end(bucket);
// BOOST_DEDUCED_TYPENAME X::const_local_iterator
// lit = x1.begin(bucket), lend = x1.end(bucket);
// for(; lit != lend && !eq(get_key<X>(*lit), key); ++lit) continue;
// if(lit == lend)
// BOOST_ERROR("Unable to find element with a local_iterator");
@@ -81,7 +86,8 @@ namespace test
// BOOST_ERROR("Element count doesn't match local_iterator.");
// for(; lit != lend; ++lit) {
// if(eq(get_key<X>(*lit), key)) {
// BOOST_ERROR("Non-adjacent element with equivalent key in bucket.");
// BOOST_ERROR("Non-adjacent element with equivalent key "
// "in bucket.");
// break;
// }
// }
@@ -90,7 +96,8 @@ namespace test
// Finally, check that size matches up.
if(x1.size() != size)
BOOST_ERROR("x1.size() doesn't match actual size.");
float load_factor = static_cast<float>(size) / static_cast<float>(x1.bucket_count());
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.");
+69 -17
View File
@@ -1,5 +1,5 @@
// Copyright 2008 Daniel James.
// 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)
@@ -17,18 +17,38 @@
namespace test
{
template <typename It1, typename It2>
bool equal(It1 begin, It1 end, It2 compare)
{
for(;begin != end; ++begin, ++compare)
if(*begin != *compare) return false;
return true;
}
template <typename It1, typename It2, typename Pred>
bool equal(It1 begin, It1 end, It2 compare, Pred predicate)
{
for(;begin != end; ++begin, ++compare)
if(!predicate(*begin, *compare)) return false;
return true;
}
template <typename T> class list;
namespace test_detail
{
template <typename T> struct list_node;
template <typename T> class list_node;
template <typename T> class list_data;
template <typename T> class list_iterator;
template <typename T> class list_const_iterator;
template <typename T>
struct list_node
class list_node
{
list_node(list_node const&);
list_node& operator=(list_node const&);
public:
T value_;
list_node* next_;
@@ -74,14 +94,14 @@ namespace test
node* ptr_;
public:
list_iterator() : ptr_(0) {};
list_iterator() : ptr_(0) {}
explicit list_iterator(node* x) : ptr_(x) {}
T& operator*() const { return ptr_->value_; }
T* operator->() const { return &ptr_->value_; }
list_iterator& operator++() {
ptr_ = ptr_->next_; return *this; }
list_iterator& operator++(int) {
list_iterator operator++(int) {
list_iterator tmp = *this; ptr_ = ptr_->next_; return tmp; }
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
@@ -106,12 +126,29 @@ namespace test
T const& operator*() const { return ptr_->value_; }
T const* operator->() const { return &ptr_->value_; }
list_const_iterator& operator++() {
ptr_ = ptr_->next_; return *this; }
list_const_iterator& operator++(int) {
list_const_iterator tmp = *this; ptr_ = ptr_->next_; return tmp; }
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
list_const_iterator& operator++()
{
ptr_ = ptr_->next_;
return *this;
}
list_const_iterator operator++(int)
{
list_const_iterator tmp = *this;
ptr_ = ptr_->next_;
return tmp;
}
bool operator==(const_iterator y) const
{
return ptr_ == y.ptr_;
}
bool operator!=(const_iterator y) const
{
return ptr_ != y.ptr_;
}
};
}
@@ -144,6 +181,7 @@ namespace test
list& operator=(list const& other) {
clear();
insert(other.begin(), other.end());
return *this;
}
iterator begin() { return iterator(data_.first_); }
@@ -218,7 +256,7 @@ namespace test
bool operator==(list const& y) const {
return size() == y.size() &&
std::equal(begin(), end(), y.begin());
test::equal(begin(), end(), y.begin());
}
bool operator!=(list const& y) const {
@@ -242,14 +280,28 @@ namespace test
node** merge_adjacent_ranges(node** first, node** second,
node** third, Less less)
{
while(first != second) {
if(less((*second)->value_, (*first)->value_)) {
swap_adjacent_ranges(first, second, third);
std::swap(second, third);
for(;;) {
for(;;) {
if(first == second) return third;
if(less((*second)->value_, (*first)->value_)) break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, second, third);
first = &(*first)->next_;
// Since the two ranges we just swapped, the order is now:
// first...third...second
for(;;) {
if(first == third) return second;
if(!less((*first)->value_, (*third)->value_)) break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, third, second);
first = &(*first)->next_;
}
return third;
}
void swap_adjacent_ranges(node** first, node** second, node** third)
+27 -24
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -18,11 +18,6 @@ namespace test
{
namespace detail
{
// This annoymous namespace won't cause ODR violations as I won't
// be linking multiple translation units together. I'll probably
// move this into a cpp file before a full release, but for now it's
// the most convenient way.
struct memory_area {
void const* start;
void const* end;
@@ -67,7 +62,8 @@ namespace test
#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;
typedef std::map<memory_area, memory_track, memory_area_compare>
type;
};
#endif
@@ -78,7 +74,8 @@ namespace test
std::pair<memory_area const, memory_track> >::type
allocator_type;
typedef BOOST_DEDUCED_TYPENAME allocator_memory_type_gen<allocator_type>::type
typedef BOOST_DEDUCED_TYPENAME
allocator_memory_type_gen<allocator_type>::type
allocated_memory_type;
allocated_memory_type allocated_memory;
@@ -103,7 +100,7 @@ namespace test
void allocator_unref()
{
BOOST_CHECK(count_allocators > 0);
BOOST_TEST(count_allocators > 0);
if(count_allocators > 0) {
--count_allocators;
if(count_allocators == 0) {
@@ -111,19 +108,21 @@ namespace test
bool no_constructions_left = (count_constructions == 0);
bool allocated_memory_empty = allocated_memory.empty();
// Clearing the data before the checks terminate the tests.
// Clearing the data before the checks terminate the
// tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
BOOST_CHECK(no_allocations_left);
BOOST_CHECK(no_constructions_left);
BOOST_CHECK(allocated_memory_empty);
BOOST_TEST(no_allocations_left);
BOOST_TEST(no_constructions_left);
BOOST_TEST(allocated_memory_empty);
}
}
}
void track_allocate(void *ptr, std::size_t n, std::size_t size, int tag)
void track_allocate(void *ptr, std::size_t n, std::size_t size,
int tag)
{
if(n == 0) {
BOOST_ERROR("Allocating 0 length array.");
@@ -137,30 +136,34 @@ namespace test
}
}
void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag)
void track_deallocate(void* ptr, std::size_t n, std::size_t size,
int tag)
{
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos
= allocated_memory.find(memory_area(ptr, (char*) ptr + n * size));
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos =
allocated_memory.find(
memory_area(ptr, (char*) ptr + n * size));
if(pos == allocated_memory.end()) {
BOOST_ERROR("Deallocating unknown pointer.");
} else {
BOOST_CHECK(pos->first.start == ptr);
BOOST_CHECK(pos->first.end == (char*) ptr + n * size);
BOOST_CHECK(pos->second.tag_ == tag);
BOOST_TEST(pos->first.start == ptr);
BOOST_TEST(pos->first.end == (char*) ptr + n * size);
BOOST_TEST(pos->second.tag_ == tag);
allocated_memory.erase(pos);
}
BOOST_CHECK(count_allocations > 0);
BOOST_TEST(count_allocations > 0);
if(count_allocations > 0) --count_allocations;
}
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
void track_construct(void* /*ptr*/, std::size_t /*size*/,
int /*tag*/)
{
++count_constructions;
}
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
void track_destroy(void* /*ptr*/, std::size_t /*size*/,
int /*tag*/)
{
BOOST_CHECK(count_constructions > 0);
BOOST_TEST(count_constructions > 0);
if(count_constructions > 0) --count_constructions;
}
};
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-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)
+11
View File
@@ -0,0 +1,11 @@
// Copyright 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(_WIN32_WCE)
// The standard windows mobile headers trigger this warning so I disable it
// before doing anything else.
#pragma warning(disable:4201) // nonstandard extension used :
// nameless struct/union
#endif
+4 -2
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-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)
@@ -71,7 +71,9 @@ namespace test
type_ == generate_collisions ?
generate(int_ptr) % 10 : 1;
count; --count) {
x.push_back(std::pair<key_type const, mapped_type>(key, generate(mapped_ptr)));
x.push_back(
std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr)));
}
}
}
+8 -4
View File
@@ -1,5 +1,5 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-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)
@@ -20,18 +20,22 @@ namespace test
{
typedef test::list<BOOST_DEDUCED_TYPENAME X::value_type> values_type;
values_type values_;
unsigned int allocations_;
public:
void store(X const& x) {
void store(X const& x, unsigned int allocations = 0) {
DISABLE_EXCEPTIONS;
values_.clear();
values_.insert(x.cbegin(), x.cend());
allocations_ = allocations;
}
void test(X const& x) const {
void test(X const& x, unsigned int allocations = 0) const {
if(!(x.size() == values_.size() &&
std::equal(x.cbegin(), x.cend(), values_.begin(),
test::equal(x.cbegin(), x.cend(), values_.begin(),
test::equivalent)))
BOOST_ERROR("Strong exception safety failure.");
if(allocations != allocations_)
BOOST_ERROR("Strong exception failure: extra allocations.");
}
};
}
+30 -36
View File
@@ -1,36 +1,30 @@
// Copyright 2006-2008 Daniel James.
// 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_TEST_HEADER)
#define BOOST_UNORDERED_TEST_TEST_HEADER
#if defined(BOOST_UNORDERED_FULL_TEST)
#include <boost/test/test_tools.hpp>
#define UNORDERED_AUTO_TEST(x) BOOST_AUTO_TEST_CASE(x)
#define RUN_TESTS()
#else
#include <boost/test/minimal.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>
#define UNORDERED_AUTO_TEST(x) \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base { \
BOOST_PP_CAT(x, _type)() \
: ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
{ \
::test::test_list::add_test(this); \
} \
void run(); \
}; \
BOOST_PP_CAT(x, _type) x; \
void BOOST_PP_CAT(x, _type)::run()
#define RUN_TESTS() int test_main(int, char**) { ::test::test_list::run_tests(); return 0; }
#define UNORDERED_AUTO_TEST(x) \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base { \
BOOST_PP_CAT(x, _type)() \
: ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
{ \
::test::test_list::add_test(this); \
} \
void run(); \
}; \
BOOST_PP_CAT(x, _type) x; \
void BOOST_PP_CAT(x, _type)::run() \
#define RUN_TESTS() int main(int, char**) \
{ ::test::test_list::run_tests(); return boost::report_errors(); } \
namespace test {
struct registered_test_base {
@@ -74,8 +68,6 @@ namespace test {
}
}
#endif
#include <boost/preprocessor/seq/for_each_product.hpp>
#include <boost/preprocessor/seq/fold_left.hpp>
#include <boost/preprocessor/seq/to_tuple.hpp>
@@ -83,20 +75,22 @@ namespace test {
#include <boost/preprocessor/cat.hpp>
// 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)
#define UNORDERED_TEST(name, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name)) parameters) \
#define UNORDERED_TEST_OP(r, product) \
UNORDERED_TEST_OP2( \
BOOST_PP_SEQ_HEAD(product), \
BOOST_PP_SEQ_TAIL(product))
#define UNORDERED_TEST_OP(r, product) \
UNORDERED_TEST_OP2( \
BOOST_PP_SEQ_HEAD(product), \
BOOST_PP_SEQ_TAIL(product)) \
#define UNORDERED_TEST_OP2(name, params) \
UNORDERED_AUTO_TEST(BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) { \
name BOOST_PP_SEQ_TO_TUPLE(params); \
}
#define UNORDERED_TEST_OP2(name, params) \
UNORDERED_AUTO_TEST( \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) \
{ \
name BOOST_PP_SEQ_TO_TUPLE(params); \
} \
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem)) \
#endif
+48 -27
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -27,7 +27,8 @@ namespace test
{
template <class X>
struct equals_to_compare2
: public boost::mpl::identity<std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> >
: public boost::mpl::identity<
std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> >
{
};
@@ -49,8 +50,8 @@ namespace test
value_list values2(x2.begin(), x2.end());
values1.sort();
values2.sort();
BOOST_CHECK(values1.size() == values2.size() &&
std::equal(values1.begin(), values1.end(), values2.begin(),
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent));
}
@@ -61,38 +62,56 @@ namespace test
test::list<T> values2(x2.first, x2.second);
values1.sort();
values2.sort();
BOOST_CHECK(values1.size() == values2.size() &&
std::equal(values1.begin(), values1.end(), values2.begin(), test::equivalent));
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(),
values2.begin(), test::equivalent));
}
template <class X>
struct ordered_set
: public boost::mpl::if_<
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>
> {};
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 <class X>
struct ordered_map
: public boost::mpl::if_<
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>
> {};
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 X>
struct ordered_base
: public boost::mpl::eval_if<
struct ordered_base : public
boost::mpl::eval_if<
test::is_set<X>,
test::ordered_set<X>,
test::ordered_map<X> >
{
};
test::ordered_map<X>
> {};
template <class X>
class ordered : public ordered_base<X>::type
@@ -114,7 +133,8 @@ namespace test
compare_range(x, *this);
}
void compare_key(X const& x, BOOST_DEDUCED_TYPENAME X::value_type const& val)
void compare_key(X const& x,
BOOST_DEDUCED_TYPENAME X::value_type const& val)
{
compare_pairs(
x.equal_range(get_key<X>(val)),
@@ -132,7 +152,8 @@ namespace test
};
template <class Equals>
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type create_compare(Equals const&)
BOOST_DEDUCED_TYPENAME
equals_to_compare<Equals>::type create_compare(Equals const&)
{
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type x;
return x;
+2 -2
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -347,7 +347,7 @@ namespace exception
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
}
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
UNORDERED_SCOPE(allocator::construct(pointer, Args&&...)) {
UNORDERED_EPOINT("Mock allocator construct function.");
+1 -1
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
+52 -17
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -46,31 +46,61 @@ namespace minimal
class copy_constructible_equality_comparable
{
public:
static copy_constructible_equality_comparable create() { return copy_constructible_equality_comparable(); }
copy_constructible_equality_comparable(copy_constructible_equality_comparable const&) {}
~copy_constructible_equality_comparable() {}
static copy_constructible_equality_comparable create() {
return copy_constructible_equality_comparable();
}
copy_constructible_equality_comparable(
copy_constructible_equality_comparable const&)
{
}
~copy_constructible_equality_comparable()
{
}
private:
copy_constructible_equality_comparable& operator=(copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable& operator=(
copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable() {}
};
bool operator==(copy_constructible_equality_comparable, copy_constructible_equality_comparable) {
bool operator==(
copy_constructible_equality_comparable,
copy_constructible_equality_comparable)
{
return true;
}
bool operator!=(copy_constructible_equality_comparable, copy_constructible_equality_comparable) {
bool operator!=(
copy_constructible_equality_comparable,
copy_constructible_equality_comparable)
{
return false;
}
class default_copy_constructible
{
public:
static default_copy_constructible create() { return default_copy_constructible(); }
default_copy_constructible() {}
default_copy_constructible(default_copy_constructible const&) {}
~default_copy_constructible() {}
static default_copy_constructible create()
{
return default_copy_constructible();
}
default_copy_constructible()
{
}
default_copy_constructible(default_copy_constructible const&)
{
}
~default_copy_constructible()
{
}
private:
default_copy_constructible& operator=(default_copy_constructible const&);
default_copy_constructible& operator=(
default_copy_constructible const&);
};
class assignable
@@ -130,7 +160,8 @@ namespace minimal
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_); }
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_; }
@@ -169,8 +200,10 @@ namespace minimal
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_); }
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_; }
@@ -229,7 +262,7 @@ namespace minimal
void construct(pointer p, T const& t) { new((void*)p.ptr_) T(t); }
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
new((void*)p.ptr_) T(std::forward<Args>(args)...);
}
@@ -272,7 +305,9 @@ namespace boost {
namespace test {
namespace minimal {
#endif
std::size_t hash_value(test::minimal::copy_constructible_equality_comparable) {
std::size_t hash_value(
test::minimal::copy_constructible_equality_comparable)
{
return 1;
}
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+39 -9
View File
@@ -1,5 +1,5 @@
// Copyright 2006-2008 Daniel James.
// 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)
@@ -93,6 +93,10 @@ namespace test
return x1.type_ != x2.type_;
}
};
std::size_t hash_value(test::object const& x) {
return hash()(x);
}
class less
{
@@ -186,13 +190,37 @@ namespace test
template <class U> struct rebind { typedef allocator<U> other; };
explicit allocator(int t = 0) : tag_(t) { detail::tracker.allocator_ref(); }
template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_) { detail::tracker.allocator_ref(); }
allocator(allocator const& x) : tag_(x.tag_) { detail::tracker.allocator_ref(); }
~allocator() { detail::tracker.allocator_unref(); }
explicit allocator(int t = 0) : tag_(t)
{
detail::tracker.allocator_ref();
}
template <class Y> allocator(allocator<Y> const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
pointer address(reference r) { return pointer(&r); }
const_pointer address(const_reference r) { return const_pointer(&r); }
allocator(allocator const& x)
: tag_(x.tag_)
{
detail::tracker.allocator_ref();
}
~allocator()
{
detail::tracker.allocator_unref();
}
pointer address(reference r)
{
return pointer(&r);
}
const_pointer address(const_reference r)
{
return const_pointer(&r);
}
pointer allocate(size_type n) {
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
@@ -218,7 +246,7 @@ namespace test
new(p) T(t);
}
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#if defined(BOOST_UNORDERED_STD_FORWARD)
template<class... Args> void construct(pointer p, Args&&... args) {
detail::tracker.track_construct((void*) p, sizeof(T), tag_);
new(p) T(std::forward<Args>(args)...);
@@ -246,7 +274,9 @@ namespace test
};
template <class T>
bool equivalent_impl(allocator<T> const& x, allocator<T> const& y, test::derived_type) {
bool equivalent_impl(allocator<T> const& x, allocator<T> const& y,
test::derived_type)
{
return x == y;
}
+10 -3
View File
@@ -7,9 +7,15 @@ import testing ;
project unordered-test/unordered
: requirements
<toolset>intel-linux:"<cxxflags>-strict_ansi -cxxlib-icc"
<toolset>gcc:<cxxflags>"-Wsign-promo -Wunused-parameter"
#<toolset>msvc:<cxxflags>/W4
<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
;
test-suite unordered
@@ -19,6 +25,7 @@ test-suite unordered
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
[ run incomplete_test.cpp ]
[ run simple_tests.cpp ]
[ run equivalent_keys_tests.cpp ]
[ run constructor_tests.cpp ]
+47 -19
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -18,7 +20,8 @@ namespace assign_tests {
test::seed_t seed(96785);
template <class T>
void assign_tests1(T*, test::random_generator generator = test::default_generator)
void assign_tests1(T*,
test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
@@ -27,9 +30,9 @@ void assign_tests1(T*, test::random_generator generator = test::default_generato
{
T x;
x = x;
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
}
std::cerr<<"assign_tests1.2\n";
@@ -47,12 +50,13 @@ void assign_tests1(T*, test::random_generator generator = test::default_generato
y.max_load_factor(x.max_load_factor() / 20);
y = x;
tracker.compare(y);
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(x.max_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 = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
@@ -67,8 +71,8 @@ void assign_tests2(T*, test::random_generator generator = test::default_generato
T x1(v.begin(), v.end(), 0, hf1, eq1);
T x2(0, hf2, eq2);
x2 = x1;
BOOST_CHECK(test::equivalent(x2.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x2.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
test::check_container(x2, v);
}
@@ -78,17 +82,25 @@ void assign_tests2(T*, test::random_generator generator = test::default_generato
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1;
BOOST_CHECK(test::equivalent(x2.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x2.key_eq(), eq1));
BOOST_CHECK(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
test::check_container(x2, v1);
}
}
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;
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;
using test::default_generator;
using test::generate_collisions;
@@ -103,7 +115,23 @@ UNORDERED_TEST(assign_tests2,
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
std::initializer_list<std::pair<int const, int> > init;
boost::unordered_map<int, int> x1;
x1[25] = 3;
x1[16] = 10;
BOOST_TEST(!x1.empty());
x1 = init;
BOOST_TEST(x1.empty());
}
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(assign_initializer_list)
{
@@ -113,8 +141,8 @@ UNORDERED_AUTO_TEST(assign_initializer_list)
x.insert(10);
x.insert(20);
x = { 1, 2, -10 };
BOOST_CHECK(x.find(10) == x.end());
BOOST_CHECK(x.find(-10) != x.end());
BOOST_TEST(x.find(10) == x.end());
BOOST_TEST(x.find(-10) != x.end());
}
#endif
+5 -3
View File
@@ -1,8 +1,10 @@
// Copyright 2007-2008 Daniel James.
// Copyright 2007-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_map.hpp>
#include "../helpers/test.hpp"
#include <string>
@@ -16,8 +18,8 @@ UNORDERED_AUTO_TEST(at_tests) {
x["one"] = 1;
x["two"] = 2;
BOOST_CHECK(x.at("one") == 1);
BOOST_CHECK(x.at("two") == 2);
BOOST_TEST(x.at("one") == 1);
BOOST_TEST(x.at("two") == 2);
try {
x.at("three");
+36 -13
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -11,6 +13,11 @@
#include "../helpers/random_values.hpp"
#include "../helpers/helpers.hpp"
#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data.
#endif
namespace bucket_tests {
test::seed_t seed(54635);
@@ -24,7 +31,7 @@ void tests(X* = 0, test::random_generator generator = test::default_generator)
X x(v.begin(), v.end());
BOOST_CHECK(x.bucket_count() < x.max_bucket_count());
BOOST_TEST(x.bucket_count() < x.max_bucket_count());
std::cerr<<x.bucket_count()<<"<"<<x.max_bucket_count()<<"\n";
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
@@ -32,28 +39,44 @@ void tests(X* = 0, test::random_generator generator = test::default_generator)
{
size_type bucket = x.bucket(test::get_key<X>(*it));
BOOST_CHECK(bucket < x.bucket_count());
BOOST_TEST(bucket < x.bucket_count());
if(bucket < x.max_bucket_count()) {
// lit? lend?? I need a new naming scheme.
const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
while(lit != lend && test::get_key<X>(*it) != test::get_key<X>(*lit)) ++lit;
BOOST_CHECK(lit != lend);
while(lit != lend
&& test::get_key<X>(*it) != test::get_key<X>(*lit))
{
++lit;
}
BOOST_TEST(lit != lend);
}
}
for(size_type i = 0; i < x.bucket_count(); ++i) {
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x.begin(i), x.end(i)));
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x.cbegin(i), x.cend(i)));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(
std::distance(x.begin(i), x.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(
std::distance(x.cbegin(i), x.cend(i))));
X const& x_ref = x;
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x_ref.begin(i), x_ref.end(i)));
BOOST_CHECK(x.bucket_size(i) == (size_type) std::distance(x_ref.cbegin(i), x_ref.cend(i)));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(
std::distance(x_ref.begin(i), x_ref.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(
std::distance(x_ref.cbegin(i), x_ref.cend(i))));
}
}
boost::unordered_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;
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;
UNORDERED_TEST(tests, ((test_set)(test_multiset)(test_map)(test_multimap)))
+3 -1
View File
@@ -1,11 +1,13 @@
// Copyright 2006-2008 Daniel James.
// 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)
// This test creates the containers with members that meet their minimum
// requirements. Makes sure everything compiles and is defined correctly.
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <iostream>
+3 -1
View File
@@ -1,11 +1,13 @@
// Copyright 2006-2008 Daniel James.
// 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)
// This test creates the containers with members that meet their minimum
// requirements. Makes sure everything compiles and is defined correctly.
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <iostream>
+103 -44
View File
@@ -1,11 +1,13 @@
// Copyright 2005-2008 Daniel James.
// Copyright 2005-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_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#pragma warning(disable:4610) // class can never be instantiated
#pragma warning(disable:4510) // default constructor could not be generated
#endif
#include <boost/concept_check.hpp>
@@ -35,10 +37,15 @@ void container_test(X& r, T const&)
typedef BOOST_DEDUCED_TYPENAME X::difference_type difference_type;
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<iterator>::type iterator_value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<const_iterator>::type const_iterator_value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<iterator>::type iterator_difference_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<const_iterator>::type const_iterator_difference_type;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_value<iterator>::type iterator_value_type;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_value<const_iterator>::type const_iterator_value_type;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<iterator>::type iterator_difference_type;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<const_iterator>::type
const_iterator_difference_type;
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME X::reference reference;
@@ -87,10 +94,10 @@ void container_test(X& r, T const&)
// I'm not sure about either of these tests...
size_type max_diff((std::numeric_limits<difference_type>::max)());
difference_type converted_diff(max_diff);
BOOST_CHECK((std::numeric_limits<difference_type>::max)()
BOOST_TEST((std::numeric_limits<difference_type>::max)()
== converted_diff);
BOOST_CHECK(
BOOST_TEST(
static_cast<comparison_type>(
(std::numeric_limits<size_type>::max)()) >
static_cast<comparison_type>(
@@ -98,8 +105,8 @@ void container_test(X& r, T const&)
// I don't test the runtime post-conditions here.
X u;
BOOST_CHECK(u.size() == 0);
BOOST_CHECK(X().size() == 0);
BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0);
X a,b;
@@ -131,6 +138,12 @@ void container_test(X& r, T const&)
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
// Avoid unused variable warnings:
sink(u);
sink(u2);
sink(u3);
}
template <class X, class Key>
@@ -147,18 +160,17 @@ 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_MPL_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >));
r.insert(std::pair<Key const, T>(k, v));
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
Key k_lvalue(k);
T v_lvalue(v);
r.emplace(k, v);
r.emplace(k_lvalue, v_lvalue);
r.emplace(rvalue(k), rvalue(v));
#endif
}
template <class X>
@@ -175,9 +187,7 @@ void unordered_unique_test(X& r, T const& t)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t));
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
test::check_return_type<std::pair<iterator, bool> >::equals(r.emplace(t));
#endif
}
template <class X, class T>
@@ -185,9 +195,7 @@ void unordered_equivalent_test(X& r, T const& t)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
test::check_return_type<iterator>::equals(r.insert(t));
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
test::check_return_type<iterator>::equals(r.emplace(t));
#endif
}
template <class X, class Key, class T>
@@ -216,25 +224,57 @@ void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
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::BOOST_ITERATOR_CATEGORY<iterator>::type iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<iterator>::type iterator_difference;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<iterator>::type iterator_reference;
typedef BOOST_DEDUCED_TYPENAME
boost::BOOST_ITERATOR_CATEGORY<iterator>::type
iterator_category;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<iterator>::type
iterator_difference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type
iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<iterator>::type
iterator_reference;
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<local_iterator>::type local_iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<local_iterator>::type local_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<local_iterator>::type local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME
boost::BOOST_ITERATOR_CATEGORY<local_iterator>::type
local_iterator_category;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<local_iterator>::type
local_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type
local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<local_iterator>::type
local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<const_iterator>::type const_iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<const_iterator>::type const_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_iterator>::type const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<const_iterator>::type const_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME
boost::BOOST_ITERATOR_CATEGORY<const_iterator>::type
const_iterator_category;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<const_iterator>::type
const_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<const_iterator>::type
const_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<const_local_iterator>::type const_local_iterator_category;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<const_local_iterator>::type const_local_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_local_iterator>::type const_local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<const_local_iterator>::type const_local_iterator_reference;
typedef BOOST_DEDUCED_TYPENAME
boost::BOOST_ITERATOR_CATEGORY<const_local_iterator>::type
const_local_iterator_category;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_difference<const_local_iterator>::type
const_local_iterator_difference;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_reference<const_local_iterator>::type
const_local_iterator_reference;
BOOST_MPL_ASSERT((boost::is_same<Key, key_type>));
boost::function_requires<boost::CopyConstructibleConcept<key_type> >();
@@ -247,16 +287,25 @@ void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
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_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::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::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>));
X(10, hf, eq);
X a(10, hf, eq);
@@ -289,14 +338,12 @@ void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
const_iterator q = a.cbegin();
test::check_return_type<iterator>::equals(a.insert(q, t));
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
test::check_return_type<iterator>::equals(a.emplace_hint(q, t));
#endif
a.insert(i, j);
test::check_return_type<size_type>::equals(a.erase(k));
BOOST_CHECK(a.empty());
BOOST_TEST(a.empty());
if(a.empty()) {
a.insert(t);
q = a.cbegin();
@@ -334,4 +381,16 @@ void unordered_test(X&, Key& k, T& t, Hash& hf, Pred& eq)
test::check_return_type<float>::equals(b.max_load_factor());
a.max_load_factor((float) 2.0);
a.rehash(100);
// Avoid unused variable warnings:
sink(a);
sink(a2);
sink(a3);
sink(a4);
sink(a5);
sink(a6);
sink(a7);
sink(a8);
sink(a9);
}
+190 -76
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// Copyright 2006-2010 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"
@@ -20,7 +22,8 @@ namespace constructor_tests {
test::seed_t seed(356730);
template <class T>
void constructor_tests1(T*, test::random_generator generator = test::default_generator)
void constructor_tests1(T*,
test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
@@ -29,42 +32,42 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
std::cerr<<"Construct 1\n";
{
T x(0, hf, eq);
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr<<"Construct 2\n";
{
T x(100, hf);
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr<<"Construct 3\n";
{
T x(2000);
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 2000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 2000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr<<"Construct 4\n";
{
T x;
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
@@ -72,10 +75,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
{
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq);
BOOST_CHECK(x.bucket_count() >= 10000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
@@ -84,10 +87,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
{
test::random_values<T> v(10, generator);
T x(v.begin(), v.end(), 10000, hf);
BOOST_CHECK(x.bucket_count() >= 10000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
@@ -96,10 +99,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
{
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 100);
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
@@ -108,9 +111,9 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
{
test::random_values<T> v(1, generator);
T x(v.begin(), v.end());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
@@ -118,10 +121,10 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
std::cerr<<"Construct 9\n";
{
T x(0, hf, eq, al);
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
@@ -129,28 +132,28 @@ void constructor_tests1(T*, test::random_generator generator = test::default_gen
{
test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq, al);
BOOST_CHECK(x.bucket_count() >= 10000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr<<"Construct 11\n";
{
test::random_values<T> v(1000, generator);
T x(al);
BOOST_CHECK(x.empty());
BOOST_CHECK(test::equivalent(x.hash_function(), hf));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
}
template <class T>
void constructor_tests2(T*, test::random_generator const& generator = test::default_generator)
void constructor_tests2(T*,
test::random_generator const& generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
@@ -165,21 +168,21 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
std::cerr<<"Construct 1\n";
{
T x(10000, hf1, eq1);
BOOST_CHECK(x.bucket_count() >= 10000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x.key_eq(), eq1));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
std::cerr<<"Construct 2\n";
{
T x(100, hf1);
BOOST_CHECK(x.empty());
BOOST_CHECK(x.bucket_count() >= 100);
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x);
}
@@ -187,9 +190,9 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
{
test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1);
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x.key_eq(), eq1));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
@@ -198,10 +201,10 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
{
test::random_values<T> v(5, generator);
T x(v.begin(), v.end(), 1000, hf1);
BOOST_CHECK(x.bucket_count() >= 1000);
BOOST_CHECK(test::equivalent(x.hash_function(), hf1));
BOOST_CHECK(test::equivalent(x.key_eq(), eq));
BOOST_CHECK(test::equivalent(x.get_allocator(), al));
BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
@@ -243,21 +246,112 @@ void constructor_tests2(T*, test::random_generator const& generator = test::defa
std::cerr<<"Construct 8 - from input iterator\n";
{
test::random_values<T> v(100, generator);
T x(test::input_iterator(v.begin()), test::input_iterator(v.end()), 0, hf1, eq1);
T y(test::input_iterator(x.begin()), test::input_iterator(x.end()), 0, hf2, eq2);
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
v_begin = v.begin(), v_end = v.end();
T x(test::input_iterator(v_begin),
test::input_iterator(v_end), 0, hf1, eq1);
BOOST_DEDUCED_TYPENAME T::const_iterator
x_begin = x.begin(), x_end = x.end();
T y(test::input_iterator(x_begin),
test::input_iterator(x_end), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
std::cerr<<"Construct 8.5 - from copy iterator\n";
{
test::random_values<T> v(100, generator);
T x(test::copy_iterator(v.begin()),
test::copy_iterator(v.end()), 0, hf1, eq1);
T y(test::copy_iterator(x.begin()),
test::copy_iterator(x.end()), 0, hf2, eq2);
test::check_container(x, v);
test::check_container(y, x);
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
std::cerr<<"Construct 9\n";
{
test::random_values<T> v(100, generator);
T x(50);
BOOST_TEST(x.bucket_count() >= 50);
x.max_load_factor(10);
BOOST_TEST(x.bucket_count() >= 50);
x.insert(v.begin(), v.end());
BOOST_TEST(x.bucket_count() >= 50);
test::check_container(x, v);
test::check_equivalent_keys(x);
}
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
std::initializer_list<BOOST_DEDUCED_TYPENAME T::value_type> list;
std::cerr<<"Initializer list construct 1\n";
{
T x(list);
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
std::cerr<<"Initializer list construct 2\n";
{
T x(list, 1000);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
std::cerr<<"Initializer list construct 3\n";
{
T x(list, 10, hf1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
std::cerr<<"Initializer list construct 4\n";
{
T x(list, 10, hf1, eq1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
}
std::cerr<<"Initializer list construct 5\n";
{
T x(list, 10, hf1, eq1, al1);
BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al1));
}
#endif
}
template <class T>
void map_constructor_test(T* = 0, test::random_generator const& generator = test::default_generator)
void map_constructor_test(T* = 0,
test::random_generator const& generator = test::default_generator)
{
std::cerr<<"map_constructor_test\n";
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME T::key_type, BOOST_DEDUCED_TYPENAME T::mapped_type> > list;
typedef test::list<
std::pair<
BOOST_DEDUCED_TYPENAME T::key_type,
BOOST_DEDUCED_TYPENAME T::mapped_type
>
> list;
test::random_values<T> v(1000, generator);
list l(v.begin(), v.end());
T x(l.begin(), l.end());
@@ -266,10 +360,18 @@ void map_constructor_test(T* = 0, test::random_generator const& generator = test
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;
boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multimap;
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;
using test::default_generator;
using test::generate_collisions;
@@ -288,13 +390,25 @@ UNORDERED_TEST(map_constructor_test,
((test_map)(test_multimap))
)
#if !defined(BOOST_NO_INITIALIZER_LISTS)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_default_initializer_list) {
std::cerr<<"Initializer List Tests\n";
std::initializer_list<int> init;
boost::unordered_set<int> x1 = init;
BOOST_TEST(x1.empty());
}
#endif
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(test_initializer_list) {
std::cerr<<"Initializer List Tests\n";
boost::unordered_set<int> x1 = { 2, 10, 45, -5 };
BOOST_CHECK(x1.find(10) != x1.end());
BOOST_CHECK(x1.find(46) == x1.end());
BOOST_TEST(x1.find(10) != x1.end());
BOOST_TEST(x1.find(46) == x1.end());
}
#endif
+41 -29
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -18,7 +20,8 @@ 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 = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
@@ -27,11 +30,11 @@ void copy_construct_tests1(T*, test::random_generator const& generator = test::d
{
T x;
T y(x);
BOOST_CHECK(y.empty());
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
test::check_equivalent_keys(y);
}
@@ -41,7 +44,7 @@ void copy_construct_tests1(T*, test::random_generator const& generator = test::d
T x(v.begin(), v.end());
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
equivalent(y);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
}
@@ -55,15 +58,16 @@ void copy_construct_tests1(T*, test::random_generator const& generator = test::d
x.max_load_factor(x.load_factor() / 4);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
equivalent(y);
BOOST_TEST(equivalent(y));
// This isn't guaranteed:
BOOST_CHECK(y.load_factor() < y.max_load_factor());
BOOST_TEST(y.load_factor() < y.max_load_factor());
test::check_equivalent_keys(y);
}
}
template <class T>
void copy_construct_tests2(T* ptr, test::random_generator const& generator = test::default_generator)
void copy_construct_tests2(T* ptr,
test::random_generator const& generator = test::default_generator)
{
copy_construct_tests1(ptr);
@@ -75,22 +79,22 @@ void copy_construct_tests2(T* ptr, test::random_generator const& generator = tes
{
T x(10000, hf, eq, al);
T y(x);
BOOST_CHECK(y.empty());
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
test::check_equivalent_keys(y);
}
{
T x(1000, hf, eq, al);
T y(x, al2);
BOOST_CHECK(y.empty());
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al2));
BOOST_CHECK(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
test::check_equivalent_keys(y);
}
@@ -100,9 +104,9 @@ void copy_construct_tests2(T* ptr, test::random_generator const& generator = tes
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
equivalent(y);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
}
{
@@ -111,16 +115,24 @@ void copy_construct_tests2(T* ptr, test::random_generator const& generator = tes
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x, al2);
test::unordered_equivalence_tester<T> equivalent(x);
equivalent(y);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_CHECK(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
}
}
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;
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;
using test::default_generator;
using test::generate_collisions;
+69 -64
View File
@@ -1,8 +1,10 @@
// Copyright 2008 Daniel James.
// 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)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/preprocessor/seq.hpp>
@@ -28,37 +30,40 @@ namespace equality_tests
}
};
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
do { \
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_CHECK(set1 op set2); \
} while(false)
#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) \
do { \
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_CHECK(set1 op set2); \
} while(false)
#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) \
do { \
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_CHECK(map1 op map2); \
} while(false)
#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) \
do { \
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_CHECK(map1 op map2); \
} while(false)
#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) \
@@ -67,79 +72,79 @@ namespace equality_tests
UNORDERED_AUTO_TEST(equality_size_tests)
{
boost::unordered_set<int> x1, x2;
BOOST_CHECK(x1 == x2);
BOOST_CHECK(!(x1 != x2));
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x1.insert(1);
BOOST_CHECK(x1 != x2);
BOOST_CHECK(!(x1 == x2));
BOOST_CHECK(x2 != x1);
BOOST_CHECK(!(x2 == x1));
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
x2.insert(1);
BOOST_CHECK(x1 == x2);
BOOST_CHECK(!(x1 != x2));
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x2.insert(2);
BOOST_CHECK(x1 != x2);
BOOST_CHECK(!(x1 == x2));
BOOST_CHECK(x2 != x1);
BOOST_CHECK(!(x2 == x1));
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_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));
(1), !=, (501))
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(251), !=, (1)(501));
(1)(251), !=, (1)(501))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((251)(1))((1)(1)), !=, ((501)(1))((1)(1)));
((251)(1))((1)(1)), !=, ((501)(1))((1)(1)))
UNORDERED_EQUALITY_MULTISET_TEST(
(1)(501), ==, (1)(501));
(1)(501), ==, (1)(501))
UNORDERED_EQUALITY_SET_TEST(
(1)(501), ==, (501)(1));
(1)(501), ==, (501)(1))
}
UNORDERED_AUTO_TEST(equality_group_size_test)
{
UNORDERED_EQUALITY_MULTISET_TEST(
(10)(20)(20), !=, (10)(10)(20));
(10)(20)(20), !=, (10)(10)(20))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((10)(1))((20)(1))((20)(1)), !=,
((10)(1))((20)(1))((10)(1)));
((10)(1))((20)(1))((10)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((20)(1))((10)(1))((10)(1)), ==,
((10)(1))((20)(1))((10)(1)));
((10)(1))((20)(1))((10)(1)))
}
UNORDERED_AUTO_TEST(equality_map_value_test)
{
UNORDERED_EQUALITY_MAP_TEST(
((1)(1)), !=, ((1)(2)));
((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MAP_TEST(
((1)(1)), ==, ((1)(1)));
((1)(1)), ==, ((1)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(1)), !=, ((1)(2)));
((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)));
((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(
((1)(2))((1)(1)), !=, ((1)(1))((1)(2)));
((1)(2))((1)(1)), !=, ((1)(1))((1)(2)))
}
UNORDERED_AUTO_TEST(equality_predicate_test)
{
UNORDERED_EQUALITY_SET_TEST(
(1), ==, (1001));
(1), ==, (1001))
UNORDERED_EQUALITY_MAP_TEST(
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)));
((1)(2))((1001)(1)), ==, ((1001)(2))((1)(1)))
}
// Test that equality still works when the two containers have
@@ -150,15 +155,15 @@ namespace equality_tests
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_CHECK(set1 == set2);
BOOST_TEST(set1 == set2);
set1.insert(1); set2.insert(2);
BOOST_CHECK(set1 != set2);
BOOST_TEST(set1 != set2);
set1.insert(2); set2.insert(1);
BOOST_CHECK(set1 == set2);
BOOST_TEST(set1 == set2);
set1.insert(10); set2.insert(20);
BOOST_CHECK(set1 != set2);
BOOST_TEST(set1 != set2);
set1.insert(20); set2.insert(10);
BOOST_CHECK(set1 == set2);
BOOST_TEST(set1 == set2);
}
}
+16 -11
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -42,17 +44,20 @@ UNORDERED_AUTO_TEST(set_tests)
{986, 25, 986}
};
test_equal_insertion<boost::unordered_set<int> >(values[0], values[0] + 1);
test_equal_insertion<boost::unordered_set<int> >(values[1], values[1] + 2);
test_equal_insertion<boost::unordered_set<int> >(values[2], values[2] + 2);
test_equal_insertion<boost::unordered_set<int> >(values[3], values[3] + 2);
test_equal_insertion<boost::unordered_set<int> >(values[4], values[4] + 3);
typedef boost::unordered_set<int> set;
typedef boost::unordered_multiset<int> multiset;
test_equal_insertion<boost::unordered_multiset<int> >(values[0], values[0] + 1);
test_equal_insertion<boost::unordered_multiset<int> >(values[1], values[1] + 2);
test_equal_insertion<boost::unordered_multiset<int> >(values[2], values[2] + 2);
test_equal_insertion<boost::unordered_multiset<int> >(values[3], values[3] + 2);
test_equal_insertion<boost::unordered_multiset<int> >(values[4], values[4] + 3);
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
test_equal_insertion<set>(values[2], values[2] + 2);
test_equal_insertion<set>(values[3], values[3] + 2);
test_equal_insertion<set>(values[4], values[4] + 3);
test_equal_insertion<multiset>(values[0], values[0] + 1);
test_equal_insertion<multiset>(values[1], values[1] + 2);
test_equal_insertion<multiset>(values[2], values[2] + 2);
test_equal_insertion<multiset>(values[3], values[3] + 2);
test_equal_insertion<multiset>(values[4], values[4] + 3);
}
UNORDERED_AUTO_TEST(map_tests)
+17 -9
View File
@@ -1,11 +1,13 @@
// Copyright 2006-2008 Daniel James.
// 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)
// The code for erasing elements from containers with equivalent keys is very
// hairy with several tricky edge cases - so explicitly test each one.
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
#include "../helpers/list.hpp"
@@ -15,6 +17,11 @@
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data.
#endif
struct write_pair_type
{
template <class X1, class X2>
@@ -67,11 +74,11 @@ UNORDERED_AUTO_TEST(single_item_tests)
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.begin());
BOOST_CHECK(x.count(1) == 1 && x.size() == 1);
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
x.erase(x.end(), x.end());
BOOST_CHECK(x.count(1) == 1 && x.size() == 1);
BOOST_TEST(x.count(1) == 1 && x.size() == 1);
x.erase(x.begin(), x.end());
BOOST_CHECK(x.count(1) == 0 && x.size() == 0);
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
}
UNORDERED_AUTO_TEST(two_equivalent_item_tests)
@@ -83,14 +90,14 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
{
collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.end());
BOOST_CHECK(x.count(1) == 0 && x.size() == 0);
BOOST_TEST(x.count(1) == 0 && x.size() == 0);
}
{
collide_map x(init.begin(), init.end());
int value = boost::next(x.begin())->second;
x.erase(x.begin(), boost::next(x.begin()));
BOOST_CHECK(x.count(1) == 1 && x.size() == 1 &&
BOOST_TEST(x.count(1) == 1 && x.size() == 1 &&
x.begin()->first == 1 && x.begin()->second == value);
}
@@ -98,7 +105,7 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
collide_map x(init.begin(), init.end());
int value = x.begin()->second;
x.erase(boost::next(x.begin()), x.end());
BOOST_CHECK(x.count(1) == 1 && x.size() == 1 &&
BOOST_TEST(x.count(1) == 1 && x.size() == 1 &&
x.begin()->first == 1 && x.begin()->second == value);
}
}
@@ -116,7 +123,7 @@ bool compare(Range1 const& x, Range2 const& y)
}
template <class Container>
bool general_erase_range_test(Container& x, int start, int end)
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));
@@ -128,7 +135,8 @@ template <class Container>
void erase_subrange_tests(Container const& x)
{
for(std::size_t length = 0; length < x.size(); ++length) {
for(std::size_t position = 0; position < x.size() - length; ++position) {
for(std::size_t position = 0; position < x.size() - length; ++position)
{
Container y(x);
collide_list init(y.begin(), y.end());
if(!general_erase_range_test(y, position, position + length)) {
+99 -34
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -21,21 +23,22 @@ namespace erase_tests
test::seed_t seed(85638);
template <class Container>
void erase_tests1(Container*, test::random_generator generator = test::default_generator)
void erase_tests1(Container*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"Erase by key.\n";
{
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
for(BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator it = v.begin();
it != v.end(); ++it)
for(BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
it = v.begin(); it != v.end(); ++it)
{
std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size();
BOOST_CHECK(count == x.erase(test::get_key<Container>(*it)));
BOOST_CHECK(x.size() == old_size - count);
BOOST_CHECK(x.count(test::get_key<Container>(*it)) == 0);
BOOST_CHECK(x.find(test::get_key<Container>(*it)) == x.end());
BOOST_TEST(count == x.erase(test::get_key<Container>(*it)));
BOOST_TEST(x.size() == old_size - count);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
}
}
@@ -46,15 +49,17 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
std::size_t size = x.size();
while(size > 0 && !x.empty())
{
BOOST_DEDUCED_TYPENAME Container::key_type key = test::get_key<Container>(*x.begin());
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
BOOST_DEDUCED_TYPENAME Container::iterator pos = x.erase(x.begin());
BOOST_DEDUCED_TYPENAME Container::iterator
pos = x.erase(x.begin());
--size;
BOOST_CHECK(pos == x.begin());
BOOST_CHECK(x.count(key) == count - 1);
BOOST_CHECK(x.size() == size);
BOOST_TEST(pos == x.begin());
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
}
BOOST_CHECK(x.empty());
BOOST_TEST(x.empty());
}
std::cerr<<"erase(random position).\n";
@@ -65,7 +70,7 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
while(size > 0 && !x.empty())
{
using namespace std;
int index = rand() % x.size();
int index = rand() % (int) x.size();
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if(index == 0) {
prev = pos = x.begin();
@@ -75,17 +80,18 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
pos = boost::next(prev);
}
next = boost::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key = test::get_key<Container>(*pos);
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_CHECK(next == x.erase(pos));
BOOST_TEST(next == x.erase(pos));
--size;
if(size > 0)
BOOST_CHECK(index == 0 ? next == x.begin() :
BOOST_TEST(index == 0 ? next == x.begin() :
next == boost::next(prev));
BOOST_CHECK(x.count(key) == count - 1);
BOOST_CHECK(x.size() == size);
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
}
BOOST_CHECK(x.empty());
BOOST_TEST(x.empty());
}
std::cerr<<"erase(ranges).\n";
@@ -99,33 +105,92 @@ void erase_tests1(Container*, test::random_generator generator = test::default_g
// returns 'the iterator immediately following the erase elements'
// and if nothing is erased, then there's nothing to follow. But I
// think this is the only sensible option...
BOOST_CHECK(x.erase(x.end(), x.end()) == x.end());
BOOST_CHECK(x.erase(x.begin(), x.begin()) == x.begin());
BOOST_CHECK(x.size() == size);
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);
BOOST_CHECK(x.erase(x.begin(), x.end()) == x.end());
BOOST_CHECK(x.empty());
BOOST_CHECK(x.begin() == x.end());
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
BOOST_CHECK(x.erase(x.begin(), x.end()) == x.begin());
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
}
std::cerr<<"quick_erase(begin()).\n";
{
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
while(size > 0 && !x.empty())
{
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
x.quick_erase(x.begin());
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
}
BOOST_TEST(x.empty());
}
std::cerr<<"quick_erase(random position).\n";
{
test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end());
std::size_t size = x.size();
while(size > 0 && !x.empty())
{
using namespace std;
int index = rand() % (int) x.size();
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if(index == 0) {
prev = pos = x.begin();
}
else {
prev = boost::next(x.begin(), index - 1);
pos = boost::next(prev);
}
next = boost::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type
key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
x.quick_erase(pos);
--size;
if(size > 0)
BOOST_TEST(index == 0 ? next == x.begin() :
next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
}
BOOST_TEST(x.empty());
}
std::cerr<<"clear().\n";
{
test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end());
x.clear();
BOOST_CHECK(x.empty());
BOOST_CHECK(x.begin() == x.end());
BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end());
}
std::cerr<<"\n";
}
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;
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;
using test::default_generator;
using test::generate_collisions;
+82 -16
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -33,13 +35,14 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
{
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it1);
iterator pos = x.find(key);
BOOST_DEDUCED_TYPENAME X::const_iterator const_pos = x_const.find(key);
BOOST_CHECK(pos != x.end() &&
BOOST_DEDUCED_TYPENAME X::const_iterator
const_pos = x_const.find(key);
BOOST_TEST(pos != x.end() &&
x.key_eq()(key, test::get_key<X>(*pos)));
BOOST_CHECK(const_pos != x_const.end() &&
BOOST_TEST(const_pos != x_const.end() &&
x_const.key_eq()(key, test::get_key<X>(*const_pos)));
BOOST_CHECK(x.count(key) == tracker.count(key));
BOOST_TEST(x.count(key) == tracker.count(key));
test::compare_pairs(x.equal_range(key),
tracker.equal_range(key),
@@ -56,11 +59,11 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it2);
if(tracker.find(test::get_key<X>(key)) == tracker.end())
{
BOOST_CHECK(x.find(key) == x.end());
BOOST_CHECK(x_const.find(key) == x_const.end());
BOOST_CHECK(x.count(key) == 0);
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x_const.find(key) == x_const.end());
BOOST_TEST(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_CHECK(range.first == range.second);
BOOST_TEST(range.first == range.second);
}
}
}
@@ -73,18 +76,77 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
v2.begin(); it3 != v2.end(); ++it3)
{
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it3);
BOOST_CHECK(x.find(key) == x.end());
BOOST_CHECK(x.count(key) == 0);
BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_CHECK(range.first == range.second);
BOOST_TEST(range.first == range.second);
}
}
}
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;
struct compatible_key
{
test::object o_;
compatible_key(test::object const& o) : o_(o) {}
};
struct compatible_hash
{
test::hash hash_;
std::size_t operator()(compatible_key const& k) const {
return hash_(k.o_);
}
};
struct compatible_predicate
{
test::equal_to equal_;
bool operator()(compatible_key const& k1, compatible_key const& k2) const {
return equal_(k1.o_, k2.o_);
}
};
template <class X>
void find_compatible_keys_test(X*,
test::random_generator generator = test::default_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);
X x(v.begin(), v.end());
compatible_hash h;
compatible_predicate eq;
for(value_iterator it = v.begin(), end = v.end(); it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
}
test::random_values<X> v2(20, generator);
for(value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
}
}
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;
using test::default_generator;
using test::generate_collisions;
@@ -93,6 +155,10 @@ UNORDERED_TEST(find_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(find_compatible_keys_test,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
}
+11 -9
View File
@@ -1,8 +1,10 @@
// Copyright 2008 Daniel James.
// 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)
#include "../helpers/prefix.hpp"
#include <boost/unordered/unordered_map_fwd.hpp>
typedef boost::unordered_map<int, int> int_map;
@@ -42,21 +44,21 @@ UNORDERED_AUTO_TEST(use_map_fwd_declared_function) {
y[2] = 1;
call_swap(x, y);
BOOST_CHECK(y.find(1) != y.end() && y.find(1)->second == 2);
BOOST_CHECK(y.find(2) == y.end());
BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
BOOST_TEST(y.find(2) == y.end());
BOOST_CHECK(x.find(1) == x.end());
BOOST_CHECK(x.find(2) != x.end() && x.find(2)->second == 1);
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
BOOST_CHECK(!call_equals(x, y));
BOOST_CHECK(call_not_equals(x, y));
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
UNORDERED_AUTO_TEST(use_multimap_fwd_declared_function) {
int_multimap x, y;
call_swap(x, y);
BOOST_CHECK(call_equals(x, y));
BOOST_CHECK(!call_not_equals(x, y));
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
}
RUN_TESTS()
+15 -13
View File
@@ -1,8 +1,10 @@
// Copyright 2008 Daniel James.
// 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)
#include "../helpers/prefix.hpp"
#include <boost/unordered/unordered_set_fwd.hpp>
struct true_type { char x[100]; };
@@ -45,17 +47,17 @@ bool call_not_equals(int_multiset& x, int_multiset& y) {
#include "../helpers/test.hpp"
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition) {
BOOST_CHECK(sizeof(is_unordered_set_impl((int_set*) 0)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*) 0))
== sizeof(true_type));
}
#include <boost/unordered_set.hpp>
UNORDERED_AUTO_TEST(use_fwd_declared_trait) {
boost::unordered_set<int> x;
BOOST_CHECK(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
int dummy;
BOOST_CHECK(sizeof(is_unordered_set_impl(&dummy)) == sizeof(false_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*) 0)) == sizeof(false_type));
}
UNORDERED_AUTO_TEST(use_set_fwd_declared_function) {
@@ -64,21 +66,21 @@ UNORDERED_AUTO_TEST(use_set_fwd_declared_function) {
y.insert(2);
call_swap(x, y);
BOOST_CHECK(y.find(1) != y.end());
BOOST_CHECK(y.find(2) == y.end());
BOOST_TEST(y.find(1) != y.end());
BOOST_TEST(y.find(2) == y.end());
BOOST_CHECK(x.find(1) == x.end());
BOOST_CHECK(x.find(2) != x.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end());
BOOST_CHECK(!call_equals(x, y));
BOOST_CHECK(call_not_equals(x, y));
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
UNORDERED_AUTO_TEST(use_multiset_fwd_declared_function) {
int_multiset x, y;
call_swap(x, y);
BOOST_CHECK(call_equals(x, y));
BOOST_CHECK(!call_not_equals(x, y));
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
}
RUN_TESTS()
+147
View File
@@ -0,0 +1,147 @@
// Copyright 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_map.hpp>
#include <boost/unordered_set.hpp>
namespace x
{
struct D { boost::unordered_map<D, D> x; };
}
namespace test
{
// Declare, but don't define some types.
struct value;
struct hash;
struct equals;
template <class T>
struct malloc_allocator;
// Declare some instances
typedef boost::unordered_map<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > map;
typedef boost::unordered_multimap<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > multimap;
typedef boost::unordered_set<value, hash, equals,
malloc_allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals,
malloc_allocator<value> > multiset;
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
struct hash {
template <typename T>
std::size_t operator()(T const&) const { return 0; }
};
struct equals {
template <typename T>
bool operator()(T const&, T const&) const { return true; }
};
}
#include "../helpers/allocator.hpp"
namespace test
{
// Declare some members of a structs.
//
// Incomplete hash, equals and allocator aren't here supported at the
// moment.
struct struct1 {
boost::unordered_map<struct1, struct1, hash, equals,
malloc_allocator<std::pair<struct1 const, struct1> > > x;
};
struct struct2 {
boost::unordered_multimap<struct2, struct2, hash, equals,
malloc_allocator<std::pair<struct2 const, struct2> > > x;
};
struct struct3 {
boost::unordered_set<struct3, hash, equals,
malloc_allocator<struct3> > x;
};
struct struct4 {
boost::unordered_multiset<struct4, hash, equals,
malloc_allocator<struct4> > x;
};
// Now define the value type.
struct value {};
// Create some instances.
test::map m1;
test::multimap m2;
test::set s1;
test::multiset s2;
test::struct1 c1;
test::struct2 c2;
test::struct3 c3;
test::struct4 c4;
// Now declare, but don't define, the operators required for comparing
// elements.
std::size_t hash_value(value const&);
bool operator==(value const&, value const&);
std::size_t hash_value(struct1 const&);
std::size_t hash_value(struct2 const&);
std::size_t hash_value(struct3 const&);
std::size_t hash_value(struct4 const&);
bool operator==(struct1 const&, struct1 const&);
bool operator==(struct2 const&, struct2 const&);
bool operator==(struct3 const&, struct3 const&);
bool operator==(struct4 const&, struct4 const&);
// And finally use these
void use_types()
{
test::value x;
m1[x] = x;
m2.insert(std::make_pair(x, x));
s1.insert(x);
s2.insert(x);
c1.x.insert(std::make_pair(c1, c1));
c2.x.insert(std::make_pair(c2, c2));
c3.x.insert(c3);
c4.x.insert(c4);
}
// And finally define the operators required for comparing elements.
std::size_t hash_value(value const&) { return 0; }
bool operator==(value const&, value const&) { return true; }
std::size_t hash_value(struct1 const&) { return 0; }
std::size_t hash_value(struct2 const&) { return 0; }
std::size_t hash_value(struct3 const&) { return 0; }
std::size_t hash_value(struct4 const&) { return 0; }
bool operator==(struct1 const&, struct1 const&) { return true; }
bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; }
}
int main() {
// This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring.
test::use_types();
}
+24 -18
View File
@@ -1,8 +1,10 @@
// Copyright 2007-2008 Daniel James.
// Copyright 2007-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"
@@ -46,33 +48,37 @@ UNORDERED_AUTO_TEST(stable_insert_test1) {
x.insert(insert_stable::member(1,2));
x.insert(insert_stable::member(1,3));
boost::unordered_multiset<insert_stable::member>::const_iterator it = x.begin(), end = x.end();
BOOST_CHECK(it != end);
if(it != end) { BOOST_CHECK(it->tag2_ == 1); ++it; }
BOOST_CHECK(it != end);
if(it != end) { BOOST_CHECK(it->tag2_ == 2); ++it; }
BOOST_CHECK(it != end);
if(it != end) { BOOST_CHECK(it->tag2_ == 3); ++it; }
BOOST_CHECK(it == end);
boost::unordered_multiset<insert_stable::member>::const_iterator
it = x.begin(), end = x.end();
BOOST_TEST(it != end);
if(it != end) { BOOST_TEST(it->tag2_ == 1); ++it; }
BOOST_TEST(it != end);
if(it != end) { BOOST_TEST(it->tag2_ == 2); ++it; }
BOOST_TEST(it != end);
if(it != end) { BOOST_TEST(it->tag2_ == 3); ++it; }
BOOST_TEST(it == end);
}
UNORDERED_AUTO_TEST(stable_insert_test2) {
boost::unordered_multimap<insert_stable::member, int> x;
typedef boost::unordered_multimap<insert_stable::member, int>::const_iterator iterator;
typedef
boost::unordered_multimap<insert_stable::member, int>::const_iterator
iterator;
iterator it = x.insert(x.end(), std::make_pair(insert_stable::member(1,1), 1));
iterator it
= x.insert(x.end(), std::make_pair(insert_stable::member(1,1), 1));
it = x.insert(it, std::make_pair(insert_stable::member(1,2), 2));
it = x.insert(it, std::make_pair(insert_stable::member(1,3), 3));
it = x.begin();
iterator end = x.end();
BOOST_CHECK(it != end);
if(it != end) { BOOST_CHECK(it->first.tag2_ == 1 && it->second == 1); ++it; }
BOOST_CHECK(it != end);
if(it != end) { BOOST_CHECK(it->first.tag2_ == 2 && it->second == 2); ++it; }
BOOST_CHECK(it != end);
if(it != end) { BOOST_CHECK(it->first.tag2_ == 3 && it->second == 3); ++it; }
BOOST_CHECK(it == end);
BOOST_TEST(it != end);
if(it != end) { BOOST_TEST(it->first.tag2_ == 1 && it->second == 1); ++it; }
BOOST_TEST(it != end);
if(it != end) { BOOST_TEST(it->first.tag2_ == 2 && it->second == 2); ++it; }
BOOST_TEST(it != end);
if(it != end) { BOOST_TEST(it->first.tag2_ == 3 && it->second == 3); ++it; }
BOOST_TEST(it == end);
}
RUN_TESTS()
+172 -53
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// Copyright 2006-2010 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"
@@ -21,7 +23,8 @@ namespace insert_tests {
test::seed_t 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::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef test::ordered<X> ordered;
@@ -41,22 +44,24 @@ void unique_insert_tests1(X*, test::random_generator generator = test::default_g
float b = x.max_load_factor();
std::pair<iterator, bool> r1 = x.insert(*it);
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 = tracker.insert(*it);
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool>
r2 = tracker.insert(*it);
BOOST_CHECK(r1.second == r2.second);
BOOST_CHECK(*r1.first == *r2.first);
BOOST_TEST(r1.second == r2.second);
BOOST_TEST(*r1.first == *r2.first);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
template <class X>
void equivalent_insert_tests1(X*, test::random_generator generator = test::default_generator)
void equivalent_insert_tests1(X*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"insert(value) tests for containers with equivalent keys.\n";
@@ -71,21 +76,23 @@ void equivalent_insert_tests1(X*, test::random_generator generator = test::defau
float b = x.max_load_factor();
BOOST_DEDUCED_TYPENAME X::iterator r1 = x.insert(*it);
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2 = tracker.insert(*it);
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2
= tracker.insert(*it);
BOOST_CHECK(*r1 == *r2);
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
template <class X>
void insert_tests2(X*, test::random_generator generator = test::default_generator)
void insert_tests2(X*,
test::random_generator generator = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME test::ordered<X> tracker_type;
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
@@ -99,19 +106,20 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
tracker_type tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it)
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();
BOOST_DEDUCED_TYPENAME X::size_type
old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
iterator r1 = x.insert(x.begin(), *it);
tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
BOOST_CHECK(*r1 == *r2);
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
@@ -125,19 +133,20 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
tracker_type tracker = test::create_ordered(x);
test::random_values<X> v(100, generator);
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it)
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
it = v.begin(); it != v.end(); ++it)
{
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count();
BOOST_DEDUCED_TYPENAME X::size_type
old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
const_iterator r1 = x.insert(x_const.end(), *it);
tracker_iterator r2 = tracker.insert(tracker.end(), *it);
BOOST_CHECK(*r1 == *r2);
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
@@ -151,19 +160,20 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
tracker_type tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it)
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();
BOOST_DEDUCED_TYPENAME X::size_type
old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
pos = x.insert(pos, *it);
tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
BOOST_CHECK(*pos == *r2);
BOOST_TEST(*pos == *r2);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
@@ -176,10 +186,11 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
tracker_type tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for(BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it)
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();
BOOST_DEDUCED_TYPENAME X::size_type
old_bucket_count = x.bucket_count();
float b = x.max_load_factor();
x.insert(it, boost::next(it));
@@ -187,7 +198,7 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
@@ -211,17 +222,32 @@ void insert_tests2(X*, test::random_generator generator = test::default_generato
X x;
test::random_values<X> v(1000, generator);
x.insert(test::input_iterator(v.begin()), test::input_iterator(v.end()));
BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
begin = v.begin(), end = v.end();
x.insert(test::input_iterator(begin), test::input_iterator(end));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
std::cerr<<"insert copy iterator range tests.\n";
{
X x;
test::random_values<X> v(1000, generator);
x.insert(test::copy_iterator(v.begin()), test::copy_iterator(v.end()));
test::check_container(x, v);
test::check_equivalent_keys(x);
}
}
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#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 = test::default_generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef test::ordered<X> ordered;
@@ -241,22 +267,24 @@ void unique_emplace_tests1(X*, test::random_generator generator = test::default_
float b = x.max_load_factor();
std::pair<iterator, bool> r1 = x.emplace(*it);
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool> r2 = tracker.insert(*it);
std::pair<BOOST_DEDUCED_TYPENAME ordered::iterator, bool>
r2 = tracker.insert(*it);
BOOST_CHECK(r1.second == r2.second);
BOOST_CHECK(*r1.first == *r2.first);
BOOST_TEST(r1.second == r2.second);
BOOST_TEST(*r1.first == *r2.first);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(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 = test::default_generator)
{
std::cerr<<"emplace(value) tests for containers with equivalent keys.\n";
@@ -271,14 +299,15 @@ void equivalent_emplace_tests1(X*, test::random_generator generator = test::defa
float b = x.max_load_factor();
BOOST_DEDUCED_TYPENAME X::iterator r1 = x.emplace(*it);
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator r2 = tracker.insert(*it);
BOOST_DEDUCED_TYPENAME test::ordered<X>::iterator
r2 = tracker.insert(*it);
BOOST_CHECK(*r1 == *r2);
BOOST_TEST(*r1 == *r2);
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
@@ -307,18 +336,27 @@ void map_tests(X*, test::random_generator generator = test::default_generator)
tracker.compare_key(x, *it);
if(x.size() < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
template <class X>
void associative_insert_range_test(X*, test::random_generator generator = test::default_generator)
{
std::cerr<<"associative_insert_range_test\n";
// Some tests for when the range's value type doesn't match the container's
// value type.
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME X::key_type, BOOST_DEDUCED_TYPENAME X::mapped_type> > list;
template <class X>
void map_insert_range_test1(X*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"map_insert_range_test1\n";
typedef test::list<
std::pair<
BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type
>
> list;
test::random_values<X> v(1000, generator);
list l(v.begin(), v.end());
@@ -327,10 +365,37 @@ void associative_insert_range_test(X*, test::random_generator generator = test::
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;
boost::unordered_multimap<test::object, test::object, test::hash, test::equal_to, test::allocator<test::object> >* test_multimap;
template <class X>
void map_insert_range_test2(X*,
test::random_generator generator = test::default_generator)
{
std::cerr<<"map_insert_range_test2\n";
typedef test::list<
std::pair<BOOST_DEDUCED_TYPENAME X::key_type const, int>
> list;
test::random_values<
boost::unordered_map<BOOST_DEDUCED_TYPENAME X::key_type, int>
> v(1000, generator);
list l(v.begin(), v.end());
X x; x.insert(l.begin(), l.end());
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;
boost::unordered_multimap<test::object, test::object,
test::hash, test::equal_to,
test::allocator<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
@@ -350,7 +415,7 @@ UNORDERED_TEST(insert_tests2,
((default_generator)(generate_collisions))
)
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
UNORDERED_TEST(unique_emplace_tests1,
((test_set)(test_map))
((default_generator)(generate_collisions))
@@ -367,11 +432,65 @@ UNORDERED_TEST(map_tests,
((default_generator)(generate_collisions))
)
UNORDERED_TEST(associative_insert_range_test,
UNORDERED_TEST(map_insert_range_test1,
((test_map)(test_multimap))
((default_generator)(generate_collisions))
)
UNORDERED_TEST(map_insert_range_test2,
((test_map)(test_multimap))
((default_generator)(generate_collisions))
)
#if !defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && \
!defined(BOOST_NO_INITIALIZER_LISTS)
UNORDERED_AUTO_TEST(insert_initializer_list_set)
{
boost::unordered_set<int> set;
set.insert({1,2,3,1});
BOOST_TEST_EQ(set.size(), 3u);
BOOST_TEST(set.find(1) != set.end());
BOOST_TEST(set.find(4) == set.end());
}
UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
{
boost::unordered_multiset<std::string> multiset;
//multiset.insert({});
BOOST_TEST(multiset.empty());
multiset.insert({"a"});
BOOST_TEST_EQ(multiset.size(), 1u);
BOOST_TEST(multiset.find("a") != multiset.end());
BOOST_TEST(multiset.find("b") == multiset.end());
multiset.insert({"a","b"});
BOOST_TEST(multiset.size() == 3);
BOOST_TEST_EQ(multiset.count("a"), 2u);
BOOST_TEST_EQ(multiset.count("b"), 1u);
BOOST_TEST_EQ(multiset.count("c"), 0u);
}
UNORDERED_AUTO_TEST(insert_initializer_list_map)
{
boost::unordered_map<std::string, std::string> map;
//map.insert({});
BOOST_TEST(map.empty());
map.insert({{"a", "b"},{"a", "b"},{"d", ""}});
BOOST_TEST_EQ(map.size(), 2u);
}
UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
{
boost::unordered_multimap<std::string, std::string> multimap;
//multimap.insert({});
BOOST_TEST(multimap.empty());
multimap.insert({{"a", "b"},{"a", "b"},{"d", ""}});
BOOST_TEST_EQ(multimap.size(), 3u);
BOOST_TEST_EQ(multimap.count("a"), 2u);
}
#endif
}
RUN_TESTS()
+3 -1
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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>
+12 -1
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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>
@@ -11,6 +13,15 @@ void foo(boost::unordered_set<int>& x1,
boost::unordered_multiset<int>& x3,
boost::unordered_multimap<int, int>& x4)
{
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy {
boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4;
};
#endif
x1.insert(1);
x2[2] = 2;
x3.insert(3);
+10 -7
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -24,17 +26,18 @@ void set_load_factor_tests(X* = 0)
{
X x;
BOOST_CHECK(x.max_load_factor() == 1.0);
BOOST_CHECK(x.load_factor() == 0);
BOOST_TEST(x.max_load_factor() == 1.0);
BOOST_TEST(x.load_factor() == 0);
// A valid implementation could fail these tests, but I think they're
// reasonable.
x.max_load_factor(2.0); BOOST_CHECK(x.max_load_factor() == 2.0);
x.max_load_factor(0.5); BOOST_CHECK(x.max_load_factor() == 0.5);
x.max_load_factor(2.0); BOOST_TEST(x.max_load_factor() == 2.0);
x.max_load_factor(0.5); BOOST_TEST(x.max_load_factor() == 0.5);
}
template <class X>
void insert_test(X*, float mlf, test::random_generator generator = test::default_generator)
void insert_test(X*, float mlf,
test::random_generator generator = test::default_generator)
{
X x;
x.max_load_factor(mlf);
@@ -49,7 +52,7 @@ void insert_test(X*, float mlf, test::random_generator generator = test::default
old_bucket_count = x.bucket_count();
x.insert(*it);
if(old_size + 1 < b * old_bucket_count)
BOOST_CHECK(x.bucket_count() == old_bucket_count);
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
}
+55 -35
View File
@@ -1,8 +1,10 @@
// Copyright 2008 Daniel James.
// Copyright 2008-2009 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// 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/test.hpp"
@@ -44,7 +46,8 @@ 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 = test::default_generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq;
@@ -52,11 +55,11 @@ namespace move_tests
{
T y(empty(ptr));
BOOST_CHECK(y.empty());
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
BOOST_CHECK(y.max_load_factor() == 1.0);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0);
test::check_equivalent_keys(y);
}
@@ -64,21 +67,26 @@ namespace move_tests
test::random_values<T> v(1000, generator);
test::object_count count;
T y(create(v, count));
BOOST_CHECK(count == test::global_object_count);
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
}
}
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::default_generator)
{
{
test::random_values<T> v(500, generator);
test::object_count count;
T y;
y = create(v, count);
BOOST_CHECK(count == test::global_object_count);
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
}
@@ -98,51 +106,63 @@ namespace move_tests
{
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 0.5));
BOOST_CHECK(count == test::global_object_count);
#if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
BOOST_CHECK(y.max_load_factor() == 0.5); // Not necessarily required.
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
test::check_equivalent_keys(y);
}
{
// TODO: To do this correctly requires the fancy new allocator stuff.
// TODO: To do this correctly requires the fancy new allocator
// stuff.
test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 2.0), al2);
BOOST_CHECK(count != test::global_object_count);
BOOST_TEST(count != test::global_object_count);
test::check_container(y, v);
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al2));
BOOST_CHECK(y.max_load_factor() == 2.0); // Not necessarily required.
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
/*
{
test::random_values<T> v(25, generator);
T y(create(v, count, hf, eq, al, 1.0), al);
#if defined(BOOST_HAS_RVALUE_REFS)
BOOST_CHECK(count == test::global_object_count);
#if !defined(BOOST_NO_RVALUE_REFERENCES)
BOOST_TEST(count == test::global_object_count);
#else
BOOST_CHECK(test::global_object_count.constructions - count.constructions <=
BOOST_TEST(
test::global_object_count.constructions - count.constructions <=
(test::is_map<T>::value ? 50 : 25));
BOOST_CHECK(count.instances == test::global_object_count.instances);
BOOST_TEST(count.instances == test::global_object_count.instances);
#endif
test::check_container(y, v);
BOOST_CHECK(test::equivalent(y.hash_function(), hf));
BOOST_CHECK(test::equivalent(y.key_eq(), eq));
BOOST_CHECK(test::equivalent(y.get_allocator(), al));
BOOST_CHECK(y.max_load_factor() == 1.0); // Not necessarily required.
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
test::check_equivalent_keys(y);
}
}
*/ }
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;
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;
using test::default_generator;
using test::generate_collisions;
+58 -9
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -17,7 +19,8 @@ test::seed_t seed(2974);
template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
{
return x.bucket_count() > x.size() / x.max_load_factor() && x.bucket_count() >= n;
return x.bucket_count() > x.size() / x.max_load_factor() &&
x.bucket_count() >= n;
}
template <class X>
@@ -26,32 +29,72 @@ void rehash_empty_test1(X* = 0)
X x;
x.rehash(10000);
BOOST_CHECK(postcondition(x, 10000));
BOOST_TEST(postcondition(x, 10000));
x.rehash(0);
BOOST_CHECK(postcondition(x, 0));
BOOST_TEST(postcondition(x, 0));
}
template <class X>
void rehash_test1(X* = 0, test::random_generator generator = test::default_generator)
void rehash_empty_test2(X* = 0,
test::random_generator generator = test::default_generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
X x;
x.rehash(10000);
BOOST_TEST(postcondition(x, 10000));
tracker.insert_range(v.begin(), v.end());
x.insert(v.begin(), v.end());
tracker.compare(x);
BOOST_TEST(postcondition(x, 10000));
}
template <class X>
void rehash_empty_test3(X* = 0,
test::random_generator generator = test::default_generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
X x;
x.rehash(0);
BOOST_TEST(postcondition(x, 0));
tracker.insert_range(v.begin(), v.end());
x.insert(v.begin(), v.end());
tracker.compare(x);
BOOST_TEST(postcondition(x, 0));
}
template <class X>
void rehash_test1(X* = 0,
test::random_generator generator = test::default_generator)
{
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x(v.begin(), v.end());
x.rehash(0); BOOST_CHECK(postcondition(x, 0));
x.rehash(0); BOOST_TEST(postcondition(x, 0));
tracker.compare(x);
x.max_load_factor(0.25);
x.rehash(0); BOOST_CHECK(postcondition(x, 0));
x.rehash(0); BOOST_TEST(postcondition(x, 0));
tracker.compare(x);
x.max_load_factor(50.0);
x.rehash(0); BOOST_CHECK(postcondition(x, 0));
x.rehash(0); BOOST_TEST(postcondition(x, 0));
tracker.compare(x);
x.rehash(1000); BOOST_CHECK(postcondition(x, 1000));
x.rehash(1000); BOOST_TEST(postcondition(x, 1000));
tracker.compare(x);
}
@@ -63,6 +106,12 @@ boost::unordered_multimap<int, int>* int_multimap_ptr;
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))
)
+30 -26
View File
@@ -1,10 +1,12 @@
// Copyright 2006-2008 Daniel James.
// 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)
// This test checks the runtime requirements of containers.
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/test.hpp"
@@ -19,67 +21,69 @@ void simple_test(X const& a)
{
X u;
BOOST_CHECK(u.size() == 0);
BOOST_CHECK(X().size() == 0);
BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0);
}
{
BOOST_CHECK(equivalent(X(a)));
BOOST_TEST(equivalent(X(a)));
}
{
X u(a);
BOOST_CHECK(equivalent(u));
BOOST_TEST(equivalent(u));
}
{
X u = a;
BOOST_CHECK(equivalent(u));
BOOST_TEST(equivalent(u));
}
{
X b(a);
BOOST_CHECK(b.begin() == const_cast<X const&>(b).cbegin());
BOOST_CHECK(b.end() == const_cast<X const&>(b).cend());
BOOST_TEST(b.begin() == const_cast<X const&>(b).cbegin());
BOOST_TEST(b.end() == const_cast<X const&>(b).cend());
}
{
X b(a);
X c;
BOOST_CHECK(equivalent(b));
BOOST_CHECK(c.empty());
BOOST_TEST(equivalent(b));
BOOST_TEST(c.empty());
b.swap(c);
BOOST_CHECK(b.empty());
BOOST_CHECK(equivalent(c));
BOOST_TEST(b.empty());
BOOST_TEST(equivalent(c));
b.swap(c);
BOOST_CHECK(c.empty());
BOOST_CHECK(equivalent(b));
BOOST_TEST(c.empty());
BOOST_TEST(equivalent(b));
}
{
X u;
X& r = u;
BOOST_CHECK(&(r = r) == &r);
BOOST_CHECK(r.empty());
BOOST_CHECK(&(r = a) == &r);
BOOST_CHECK(equivalent(r));
BOOST_CHECK(&(r = r) == &r);
BOOST_CHECK(equivalent(r));
BOOST_TEST(&(r = r) == &r);
BOOST_TEST(r.empty());
BOOST_TEST(&(r = a) == &r);
BOOST_TEST(equivalent(r));
BOOST_TEST(&(r = r) == &r);
BOOST_TEST(equivalent(r));
}
{
BOOST_CHECK(a.size() ==
(BOOST_DEDUCED_TYPENAME X::size_type) std::distance(a.begin(), a.end()));
BOOST_TEST(a.size() ==
static_cast<BOOST_DEDUCED_TYPENAME X::size_type>(
std::distance(a.begin(), a.end())));
}
{
BOOST_CHECK(a.empty() == (a.size() == 0));
BOOST_TEST(a.empty() == (a.size() == 0));
}
{
BOOST_CHECK(a.empty() == (a.begin() == a.end()));
BOOST_TEST(a.empty() == (a.begin() == a.end()));
X u;
BOOST_CHECK(u.begin() == u.end());
BOOST_TEST(u.begin() == u.end());
}
}
@@ -91,7 +95,7 @@ UNORDERED_AUTO_TEST(simple_tests)
std::cout<<"Test unordered_set.\n";
boost::unordered_set<int> set;
simple_test(set);
set.insert(1); set.insert(2); set.insert(1456);
simple_test(set);
+23 -9
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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/config.hpp>
#include <algorithm>
#include <iterator>
@@ -60,7 +62,8 @@ 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 = 0,
test::random_generator generator = test::default_generator)
{
swap_tests1(ptr);
@@ -96,7 +99,8 @@ void swap_tests2(X* ptr = 0, test::random_generator generator = test::default_ge
X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
try {
swap_test_impl(x, y);
BOOST_ERROR("Using swap method 1, swapping with unequal allocators didn't throw.");
BOOST_ERROR("Using swap method 1, "
"swapping with unequal allocators didn't throw.");
} catch (std::runtime_error) {}
}
#else
@@ -109,18 +113,28 @@ void swap_tests2(X* ptr = 0, test::random_generator generator = test::default_ge
{
test::random_values<X> vx(100, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1), allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2), allocator_type(2));
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1),
allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2),
allocator_type(2));
swap_test_impl(x, y);
swap_test_impl(x, y);
}
#endif
}
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;
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;
UNORDERED_TEST(swap_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
+60 -30
View File
@@ -1,8 +1,10 @@
// Copyright 2006-2008 Daniel James.
// 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"
@@ -29,7 +31,7 @@ namespace unnecessary_copy_tests
: tag_(x.tag_) { ++copies; }
count_copies(count_copies const& x) : tag_(x.tag_) { ++copies; }
#if defined(BOOST_HAS_RVALUE_REFS)
#if !defined(BOOST_NO_RVALUE_REFERENCES)
count_copies(count_copies&& x) : tag_(x.tag_) {
x.tag_ = -1; ++moves;
}
@@ -65,15 +67,33 @@ namespace unnecessary_copy_tests
}
}
#define COPY_COUNT(n) \
if(count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \
std::cerr<<"Number of copies: "<<count_copies::copies<<std::endl; \
#define COPY_COUNT(n) \
if(count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \
std::cerr \
<< "Number of copies: " << count_copies::copies \
<< " expecting: " << n << std::endl; \
}
#define MOVE_COUNT(n) \
if(count_copies::moves != n) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr<<"Number of moves: "<<count_copies::moves<<std::endl; \
#define MOVE_COUNT(n) \
if(count_copies::moves != n) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " << count_copies::moves \
<< " expecting: " <<n << std::endl; \
}
#define COPY_COUNT_RANGE(a, b) \
if(count_copies::copies < a || count_copies::copies > b) { \
BOOST_ERROR("Wrong number of copies."); \
std::cerr \
<< "Number of copies: " << count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
#define MOVE_COUNT_RANGE(a, b) \
if(count_copies::moves < a || count_copies::moves > b) { \
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " << count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
namespace unnecessary_copy_tests
@@ -99,7 +119,6 @@ namespace unnecessary_copy_tests
UNORDERED_TEST(unnecessary_copy_insert_test,
((set)(multiset)(map)(multimap)))
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
template <class T>
void unnecessary_copy_emplace_test(T*)
{
@@ -117,9 +136,19 @@ namespace unnecessary_copy_tests
reset();
T x;
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
COPY_COUNT(1);
#else
COPY_COUNT(2);
#endif
}
UNORDERED_TEST(unnecessary_copy_emplace_test,
((set)(multiset)(map)(multimap)))
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
((set)(multiset)(map)(multimap)))
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class T>
void unnecessary_copy_emplace_move_test(T*)
{
@@ -131,13 +160,11 @@ namespace unnecessary_copy_tests
COPY_COUNT(1); MOVE_COUNT(1);
}
UNORDERED_TEST(unnecessary_copy_emplace_test,
((set)(multiset)(map)(multimap)))
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
((set)(multiset)(map)(multimap)))
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
((set)(multiset)(map)(multimap)))
#endif
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
{
reset();
@@ -172,10 +199,12 @@ namespace unnecessary_copy_tests
x.emplace(source<count_copies>());
COPY_COUNT(1); MOVE_COUNT(0);
#if !defined(BOOST_NO_RVALUE_REFERENCES)
// No move should take place.
reset();
x.emplace(std::move(a));
COPY_COUNT(0); MOVE_COUNT(0);
#endif
// Just in case a did get moved...
count_copies b;
@@ -192,8 +221,12 @@ namespace unnecessary_copy_tests
// The container will have to create b copy in order to compare with
// the existing element.
//
// Note to self: If copy_count == 0 it's an error not an optimization.
// TODO: Devise a better test.
reset();
x.emplace(b, b);
COPY_COUNT(1); MOVE_COUNT(0);
}
@@ -230,24 +263,22 @@ namespace unnecessary_copy_tests
x.emplace(source<std::pair<count_copies, count_copies> >());
COPY_COUNT(2); MOVE_COUNT(0);
count_copies part;
reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
x.emplace(a_ref);
COPY_COUNT(0); MOVE_COUNT(0);
// TODO: This doesn't work on older versions of gcc.
//count_copies part;
std::pair<count_copies const, count_copies> b;
//reset();
//std::pair<count_copies const&, count_copies const&> a_ref(part, part);
//x.emplace(a_ref);
//COPY_COUNT(0); MOVE_COUNT(0);
#if !defined(BOOST_NO_RVALUE_REFERENCES)
// No move should take place.
// (since a is already in the container)
reset();
x.emplace(std::move(a));
COPY_COUNT(0); MOVE_COUNT(0);
#endif
// Just in case a did get moved
std::pair<count_copies const, count_copies> b;
// This test requires a C++0x std::pair. Which gcc hasn't got yet.
//reset();
//x.emplace(b.first.tag_);
//COPY_COUNT(2); MOVE_COUNT(0);
//
// 2 arguments
@@ -267,10 +298,9 @@ namespace unnecessary_copy_tests
COPY_COUNT(1); MOVE_COUNT(0);
reset();
x.emplace(b.first.tag_, b.second.tag_);
COPY_COUNT(2); MOVE_COUNT(0);
x.emplace(count_copies(b.first.tag_), count_copies(b.second.tag_));
COPY_COUNT(2); MOVE_COUNT(0);
}
#endif
}
RUN_TESTS()