From 38805868fc22906c9e09e30ba74ade29935d8482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 30 Aug 2011 15:49:49 +0000 Subject: [PATCH] Merged for Boost 1.48 [SVN r74161] --- doc/Jamfile.v2 | 82 ++++ doc/container.qbk | 590 ++++++++++++++++++++++++ doc/html/boostbook.css | 537 ++++++++++++++++++++++ doc/html/images/blank.png | Bin 0 -> 374 bytes doc/html/images/caution.png | Bin 0 -> 1250 bytes doc/html/images/draft.png | Bin 0 -> 17454 bytes doc/html/images/home.png | Bin 0 -> 358 bytes doc/html/images/important.png | Bin 0 -> 722 bytes doc/html/images/next.png | Bin 0 -> 336 bytes doc/html/images/note.png | Bin 0 -> 490 bytes doc/html/images/prev.png | Bin 0 -> 334 bytes doc/html/images/stable_vector.png | Bin 0 -> 7163 bytes doc/html/images/tip.png | Bin 0 -> 449 bytes doc/html/images/toc-blank.png | Bin 0 -> 318 bytes doc/html/images/toc-minus.png | Bin 0 -> 259 bytes doc/html/images/toc-plus.png | Bin 0 -> 264 bytes doc/html/images/up.png | Bin 0 -> 370 bytes doc/html/images/warning.png | Bin 0 -> 1241 bytes doc/html/reference.css | 12 + doc/index.idx | 1 + example/Jamfile.v2 | 34 ++ example/doc_emplace.cpp | 44 ++ example/doc_move_containers.cpp | 54 +++ example/doc_recursive_containers.cpp | 61 +++ example/doc_type_erasure.cpp | 91 ++++ index.html | 14 + proj/to-do.txt | 2 + proj/vc7ide/container.sln | 87 ++++ proj/vc7ide/container.vcproj | 321 +++++++++++++ proj/vc7ide/deque_test.vcproj | 138 ++++++ proj/vc7ide/flat_tree_test.vcproj | 140 ++++++ proj/vc7ide/list_ex.vcproj | 140 ++++++ proj/vc7ide/slist_test.vcproj | 138 ++++++ proj/vc7ide/stable_vector_test.vcproj | 133 ++++++ proj/vc7ide/string_test.vcproj | 139 ++++++ proj/vc7ide/tree_test.vcproj | 138 ++++++ proj/vc7ide/vector_test.vcproj | 138 ++++++ test/Jamfile.v2 | 34 ++ test/check_equal_containers.hpp | 76 ++++ test/deque_test.cpp | 295 ++++++++++++ test/dummy_test_allocator.hpp | 157 +++++++ test/emplace_test.hpp | 625 ++++++++++++++++++++++++++ test/expand_bwd_test_allocator.hpp | 193 ++++++++ test/expand_bwd_test_template.hpp | 269 +++++++++++ test/flat_tree_test.cpp | 333 ++++++++++++++ test/heap_allocator_v1.hpp | 159 +++++++ test/list_test.cpp | 78 ++++ test/list_test.hpp | 312 +++++++++++++ test/map_test.hpp | 521 +++++++++++++++++++++ test/movable_int.hpp | 230 ++++++++++ test/print_container.hpp | 64 +++ test/set_test.hpp | 504 +++++++++++++++++++++ test/slist_test.cpp | 82 ++++ test/stable_vector_test.cpp | 86 ++++ test/string_test.cpp | 293 ++++++++++++ test/tree_test.cpp | 233 ++++++++++ test/util.hpp | 113 +++++ test/vector_test.cpp | 127 ++++++ test/vector_test.hpp | 253 +++++++++++ 59 files changed, 8071 insertions(+) create mode 100644 doc/Jamfile.v2 create mode 100644 doc/container.qbk create mode 100644 doc/html/boostbook.css create mode 100644 doc/html/images/blank.png create mode 100644 doc/html/images/caution.png create mode 100644 doc/html/images/draft.png create mode 100644 doc/html/images/home.png create mode 100644 doc/html/images/important.png create mode 100644 doc/html/images/next.png create mode 100644 doc/html/images/note.png create mode 100644 doc/html/images/prev.png create mode 100644 doc/html/images/stable_vector.png create mode 100644 doc/html/images/tip.png create mode 100644 doc/html/images/toc-blank.png create mode 100644 doc/html/images/toc-minus.png create mode 100644 doc/html/images/toc-plus.png create mode 100644 doc/html/images/up.png create mode 100644 doc/html/images/warning.png create mode 100644 doc/html/reference.css create mode 100644 doc/index.idx create mode 100644 example/Jamfile.v2 create mode 100644 example/doc_emplace.cpp create mode 100644 example/doc_move_containers.cpp create mode 100644 example/doc_recursive_containers.cpp create mode 100644 example/doc_type_erasure.cpp create mode 100644 index.html create mode 100644 proj/to-do.txt create mode 100644 proj/vc7ide/container.sln create mode 100644 proj/vc7ide/container.vcproj create mode 100644 proj/vc7ide/deque_test.vcproj create mode 100644 proj/vc7ide/flat_tree_test.vcproj create mode 100644 proj/vc7ide/list_ex.vcproj create mode 100644 proj/vc7ide/slist_test.vcproj create mode 100644 proj/vc7ide/stable_vector_test.vcproj create mode 100644 proj/vc7ide/string_test.vcproj create mode 100644 proj/vc7ide/tree_test.vcproj create mode 100644 proj/vc7ide/vector_test.vcproj create mode 100644 test/Jamfile.v2 create mode 100644 test/check_equal_containers.hpp create mode 100644 test/deque_test.cpp create mode 100644 test/dummy_test_allocator.hpp create mode 100644 test/emplace_test.hpp create mode 100644 test/expand_bwd_test_allocator.hpp create mode 100644 test/expand_bwd_test_template.hpp create mode 100644 test/flat_tree_test.cpp create mode 100644 test/heap_allocator_v1.hpp create mode 100644 test/list_test.cpp create mode 100644 test/list_test.hpp create mode 100644 test/map_test.hpp create mode 100644 test/movable_int.hpp create mode 100644 test/print_container.hpp create mode 100644 test/set_test.hpp create mode 100644 test/slist_test.cpp create mode 100644 test/stable_vector_test.cpp create mode 100644 test/string_test.cpp create mode 100644 test/tree_test.cpp create mode 100644 test/util.hpp create mode 100644 test/vector_test.cpp create mode 100644 test/vector_test.hpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..4ddc031 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,82 @@ +# Boost.Container library documentation Jamfile --------------------------------- +# +# Copyright Ion Gaztanaga 2009-2011. Use, modification and +# distribution is subject to the Boost Software License, Version +# 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# See http://www.boost.org for updates, documentation, and revision history. + +import doxygen ; +import quickbook ; + +using auto-index ; + +path-constant images_location : html ; + +doxygen autodoc + : + [ glob ../../../boost/container/*.hpp ] + : + EXTRACT_ALL=NO + HIDE_UNDOC_MEMBERS=YES + EXTRACT_PRIVATE=NO + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + MACRO_EXPANSION=YES + "PREDEFINED=\"insert_const_ref_type= const T&\" \\ + \"BOOST_CONTAINER_DOXYGEN_INVOKED\" \\ + \"BOOST_RV_REF(T)=T &&\" \\ + \"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\ + \"BOOST_RV_REF_2_TEMPL_ARGS(T,a,b)=T &&\" \\ + \"BOOST_RV_REF_3_TEMPL_ARGS(T,a,b,c)=TT &&\" \\ + \"BOOST_FWD_REF(a)=a &&\"" + "boost.doxygen.reftitle=Boost.Container Header Reference" + ; + +xml container : container.qbk + : + ../../../tools/auto_index/include + ; + +boostbook standalone + : + container + : + boost.root=../../../.. + boost.libraries=../../../../libs/libraries.htm + generate.section.toc.level=3 + chunk.first.sections=1 + pdf:img.src.path=$(images_location)/ + autodoc + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html + + # Build requirements go here: + + # on (or off) one turns on (or off) indexing: + on + + # Turns on (or off) auto-index-verbose for diagnostic info. + # This is highly recommended until you have got all the many details correct! + on + + # Choose the indexing method (separately for html and PDF) - see manual. + # Choose indexing method for PDFs: + pdf:off + + # Choose indexing method for html: + html:on + + # Set the name of the script file to use (index.idx is popular): + index.idx + # Commands in the script file should all use RELATIVE PATHS + # otherwise the script will not be portable to other machines. + # Relative paths are normally taken as relative to the location + # of the script file, but we can add a prefix to all + # those relative paths using the feature. + # The path specified by may be either relative or + # absolute, for example the following will get us up to the boost root + # directory for most Boost libraries: + "../../.." + + ; diff --git a/doc/container.qbk b/doc/container.qbk new file mode 100644 index 0000000..a9c4337 --- /dev/null +++ b/doc/container.qbk @@ -0,0 +1,590 @@ +[/ + / Copyright (c) 2009-2011 Ion Gazta\u00F1aga + / + / 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) + /] + +[library Boost.Container + [quickbook 1.5] + [authors [Gaztanaga, Ion]] + [copyright 2009-2011 Ion Gaztanaga] + [id container] + [dirname container] + [purpose Containers library] + [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]) + ] +] + +[template super[x]''''''[x]''''''] +[template sub[x]''''''[x]''''''] + +[section:intro Introduction] + +[*Boost.Container] library implements several well-known containers, including +STL containers. The aim of the library is to offers advanced features not present +in standard containers or to offer the latest standard draft features for compilers +that comply with C++03. + +In short, what does [*Boost.Container] offer? + +* Move semantics are implemented, including move emulation for pre-C++11 compilers. +* New advanced features (e.g. placement insertion, recursive containers) are present. +* Containers support stateful allocators and are compatible with [*Boost.Interprocess] + (they can be safely placed in shared memory). +* The library offers new useful containers: + * [classref boost::container::flat_map flat_map], + [classref boost::container::flat_map flat_set], + [classref boost::container::flat_map flat_multiset] and + [classref boost::container::flat_map flat_multiset]: drop-in + replacements for standard associative containers but more memory friendly and with faster + searches. + * [classref boost::container::stable_vector stable_vector]: a std::list and std::vector hybrid + container: vector-like random-access iterators and list-like iterator stability in insertions and erasures. + * [classref boost::container::slist slist]: the classic pre-standard singly linked list implementation + offering constant-time `size()`. Note that C++11 `forward_list` has no `size()`. + +[section:introduction_building_container Building Boost.Container] + +There is no need to compile [*Boost.Container], since it's +a header only library. Just include your Boost header directory in your +compiler include path. + +[endsect] + +[section:tested_compilers Tested compilers] + +[*Boost.Container] requires a decent C++98 compatibility. Some compilers known to work are: + +* Visual C++ >= 7.1. +* GCC >= 3.4. +* Intel C++ >= 9.0 + +[endsect] + +[endsect] + +[section:move_emplace Efficient insertion] + +Move semantics and placement insertion are two features brought by C++11 containers +that can have a very positive impact in your C++ applications. Boost.Container implements +both techniques both for C++11 and C++03 compilers. + +[section:move_containers Move-aware containers] + +All containers offered by [*Boost.Container] can store movable-only types +and actual requirements for `value_type` depend on each container operations. +Following C++11 requirements even for C++03 compilers, many operations now require +movable or default constructible types instead of just copy constructible types. + +Containers themselves are also movable, with no-throw guarantee if allocator +or predicate (if present) copy operations are no-throw. This allows +high performance operations when transferring data between vectors. +Let's see an example: + +[import ../example/doc_move_containers.cpp] +[doc_move_containers] + +[endsect] + +[section:emplace Emplace: Placement insertion] + +All containers offered by [*Boost.Container] implement placement insertion, +which means that objects can be built directly into the container from user arguments +without creating any temporary object. For compilers without variadic templates support +placement insertion is emulated up to a finite (10) number of arguments. + +Expensive to move types are perfect candidates emplace functions and in case of node containers +([classref boost::container::list list], [classref boost::container::set set], ...) +emplace allows storing non-movable and non-copyable types in containers! Let's +see an example: + +[import ../example/doc_emplace.cpp] +[doc_emplace] + +[endsect] + +[endsect] + + +[section:containers_of_incomplete_types Containers of Incomplete Types] + +Incomplete types allow +[@http://en.wikipedia.org/wiki/Type_erasure [*type erasure ]] and +[@http://en.wikipedia.org/wiki/Recursive_data_type [*recursive data types]], and +C and C++ programmers have been using it for years to build complex data structures, like +tree structures where a node may have an arbitrary number of children. + +What about standard containers? Containers of incomplete types have been under discussion for a long time, +as explained in Matt Austern's great article ([@http://drdobbs.com/184403814 [*The Standard Librarian: Containers of Incomplete Types]]): + +["['Unlike most of my columns, this one is about something you can't do with the C++ Standard library: +put incomplete types in one of the standard containers. This column explains why you might want to +do this, why the standardization committee banned it even though they knew it was useful, and what +you might be able to do to get around the restriction.]] + +["['In 1997, shortly before the C++ Standard was completed, the standardization committee received a +query: Is it possible to create standard containers with incomplete types? It took a while for the +committee to understand the question. What would such a thing even mean, and why on earth would you +ever want to do it? The committee eventually worked it out and came up with an answer to the question. +(Just so you don't have to skip ahead to the end, the answer is "no.") But the question is much more +interesting than the answer: it points to a useful, and insufficiently discussed, programming technique. +The standard library doesn't directly support that technique, but the two can be made to coexist.]] + +["['In a future revision of C++, it might make sense to relax the restriction on instantiating +standard library templates with incomplete types. Clearly, the general prohibition should stay +in place - instantiating templates with incomplete types is a delicate business, and there are +too many classes in the standard library where it would make no sense. But perhaps it should be +relaxed on a case-by-case basis, and `vector` looks like a good candidate for such special-case +treatment: it's the one standard container class where there are good reasons to instantiate +it with an incomplete type and where Standard Library implementors want to make it work. As of +today, in fact, implementors would have to go out of their way to prohibit it!]] + +C++11 standard is also cautious about incomplete types and STL: ["['17.6.4.8 Other functions (...) 2. +the effects are undefined in the following cases: (...) In particular - if an incomplete type (3.9) +is used as a template argument when instantiating a template component, +unless specifically allowed for that component]]. Fortunately [*Boost.Container] containers are designed +to support type erasure and recursive types, so let's see some examples: + +[section:recursive_containers Recursive containers] + +All containers offered by [*Boost.Container] can be used to define recursive containers: + +[import ../example/doc_recursive_containers.cpp] +[doc_recursive_containers] + +[endsect] + +[section:type_erasure Type Erasure] + +Containers of incomplete types are useful to break header file dependencies and improve +compilation types. With Boost.Container, you can write a header file defining a class +with containers of incomplete types as data members, if you carefully put all the +implementation details that require knowing the size of the `value_type` in your +implementation file: + +[import ../example/doc_type_erasure.cpp] + +In this header file we define a class (`MyClassHolder)` that holds a `vector` of an +incomplete type (`MyClass`) that it's only forward declared. + +[doc_type_erasure_MyClassHolder_h] + +Then we can define `MyClass` in its own header file. + +[doc_type_erasure_MyClass_h] + +And include it only in the implementation file of `MyClassHolder` + +[doc_type_erasure_MyClassHolder_cpp] + +Finally, we can just compile, link, and run! + +[doc_type_erasure_main_cpp] + +[endsect] + +[endsect] + +[section:non_standard_containers Non-standard containers] + +[section:stable_vector ['stable_vector]] + +This useful, fully STL-compliant stable container [@http://bannalia.blogspot.com/2008/09/introducing-stablevector.html designed by by Joaqu\u00EDn M. L\u00F3pez Mu\u00F1oz] +is an hybrid between `vector` and `list`, providing most of +the features of `vector` except [@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#69 element contiguity]. + +Extremely convenient as they are, `vector`s have a limitation that many novice C++ programmers frequently stumble upon: +iterators and references to an element of an `vector` are invalidated when a preceding element is erased or when the +vector expands and needs to migrate its internal storage to a wider memory region (i.e. when the required size exceeds +the vector's capacity). We say then that `vector`s are unstable: by contrast, stable containers are those for which +references and iterators to a given element remain valid as long as the element is not erased: examples of stable containers +within the C++ standard library are `list` and the standard associative containers (`set`, `map`, etc.). + +Sometimes stability is too precious a feature to live without, but one particular property of `vector`s, element contiguity, +makes it impossible to add stability to this container. So, provided we sacrifice element contiguity, how much +can a stable design approach the behavior of `vector` (random access iterators, amortized constant time end +insertion/deletion, minimal memory overhead, etc.)? +The following image describes the layout of a possible data structure upon which to base the design of a stable vector: + +[$images/stable_vector.png [width 50%] [align center] ] + +Each element is stored in its own separate node. All the nodes are referenced from a contiguous array of pointers, but +also every node contains an "up" pointer referring back to the associated array cell. This up pointer is the key element +to implementing stability and random accessibility: + +Iterators point to the nodes rather than to the pointer array. This ensures stability, as it is only the pointer array +that needs to be shifted or relocated upon insertion or deletion. Random access operations can be implemented by using +the pointer array as a convenient intermediate zone. For instance, if the iterator it holds a node pointer `it.p` and we +want to advance it by n positions, we simply do: + +[c++] + + it.p = *(it.p->up+n); + +That is, we go "up" to the pointer array, add n there and then go "down" to the resulting node. + +[*General properties]. `stable_vector` satisfies all the requirements of a container, a reversible container and a sequence +and provides all the optional operations present in vector. Like vector, iterators are random access. `stable_vector` +does not provide element contiguity; in exchange for this absence, the container is stable, i.e. references and iterators +to an element of a `stable_vector` remain valid as long as the element is not erased, and an iterator that has been +assigned the return value of end() always remain valid until the destruction of the associated `stable_vector`. + +[*Operation complexity]. The big-O complexities of `stable_vector` operations match exactly those of vector. In general, +insertion/deletion is constant time at the end of the sequence and linear elsewhere. Unlike vector, `stable_vector` +does not internally perform any value_type destruction, copy/move construction/assignment operations other than those exactly +corresponding to the insertion of new elements or deletion of stored elements, which can sometimes compensate in terms of +performance for the extra burden of doing more pointer manipulation and an additional allocation per element. + +[*Exception safety]. (according to [@http://www.boost.org/community/exception_safety.html Abrahams' terminology]) +As `stable_vector` does not internally copy/move elements around, some +operations provide stronger exception safety guarantees than in vector: + +[table:stable_vector_req Exception safety + [[operation] [exception safety for `vector`] [exception safety for `stable_vector`]] + [[insert] [strong unless copy/move construction/assignment of `T` throw (basic)] [strong]] + [[erase] [no-throw unless copy/move construction/assignment of `T` throw (basic)] [no-throw]] +] + +[*Memory overhead]. The C++ standard does not specifiy requirements on memory consumption, but virtually any implementation +of `vector` has the same behavior wih respect to memory usage: the memory allocated by a `vector` v with n elements of type T +is + +m[sub v] = c\u2219e, + +where c is `v.capacity()` and e is `sizeof(T)`. c can be as low as n if the user has explicitly reserved the exact capacity +required; otherwise, the average value c for a growing `vector` oscillates between 1.25\u2219n and 1.5\u2219n for typical resizing +policies. For `stable_vector`, the memory usage is + +m[sub sv] = (c + 1)p + (n + 1)(e + p), + +where p is the size of a pointer. We have c + 1 and n + 1 rather than c and n because a dummy node is needed at the end of +the sequence. If we call f the capacity to size ratio c/n and assume that n is large enough, we have that + +m[sub sv]/m[sub v] \u2243 (fp + e + p)/fe. + +So, `stable_vector` uses less memory than `vector` only when e > p and the capacity to size ratio exceeds a given threshold: + +m[sub sv] < m[sub v] <-> f > (e + p)/(e - p). (provided e > p) + +This threshold approaches typical values of f below 1.5 when e > 5p; in a 32-bit architecture, when e > 20 bytes. + +[*Summary]. `stable_vector` is a drop-in replacement for `vector` providing stability of references and iterators, in exchange +for missing element contiguity and also some performance and memory overhead. When the element objects are expensive to +move around, the performance overhead can turn into a net performance gain for `stable_vector` if many middle insertions +or deletions are performed or if resizing is very frequent. Similarly, if the elements are large there are situations when +the memory used by `stable_vector` can actually be less than required by vector. + +['Note: Text and explanations taken from [@http://bannalia.blogspot.com/2008/09/introducing-stablevector.html Joaqu\u00EDn's blog]] + +[endsect] + +[section:flat_xxx ['flat_(multi)map/set] associative containers] + +Using sorted vectors instead of tree-based associative containers is a well-known technique in +C++ world. Matt Austern's classic article +[@http://lafstern.org/matt/col1.pdf Why You Shouldn't Use set, and What You Should Use Instead] +(C++ Report 12:4, April 2000) was enlightening: + +["['Red-black trees aren't the only way to organize data that permits lookup in logarithmic time. One of the basic +algorithms of computer science is binary search, which works by successively dividing a range in half. Binary +search is log N and it doesn't require any fancy data structures, just a sorted collection of elements. +(...) You can use whatever data structure is convenient, so long as it provides STL iterator; +usually it's easiest to use a C array, or a vector.]] + +["['Both std::lower_bound and set::find take time proportional to log N, but the constants of proportionality +are very different. Using g++ (...) it takes X seconds to perform a million lookups in a +sorted vector of a million elements, and almost twice as long (...) using a set. Moreover, +the set uses almost three times as much memory (48 million bytes) as the vector (16.8 million).]] + +["['Using a sorted vector instead of a set gives you faster lookup and much faster iteration, +but at the cost of slower insertion. Insertion into a set, using set::insert, is proportional +to log N, but insertion into a sorted vector, (...) +, is proportional to N. Whenever you insert something into a vector, +vector::insert has to make room by shifting all of the elements that follow it. On average, if you're equally +likely to insert a new element anywhere, you'll be shifting N/2 elements.]] + +["['It may sometimes be convenient to bundle all of this together into a small container adaptor. +This class does not satisfy the requirements of a Standard Associative Container, since the complexity of insert is +O(N) rather than O(log N), but otherwise it is almost a drop-in replacement for set.]] + +Following Matt Austern's indications, Andrei Alexandrescu's +[@http://www.bestwebbuys.com/Modern-C-Design-Generic-Programming-and-Design-Patterns-Applied-ISBN-9780201704310?isrc=-rd Modern C++ Design] +showed `AssocVector`, a `std::map` drop-in +replacement designed in his [@http://loki-lib.sourceforge.net/ Loki] library: + +["['It seems as if we're better off with a sorted vector. The disadvantages of a sorted +vector are linear-time insertions and linear-time deletions (...). In exchange, a vector +offers about twice the lookup speed and a much smaller working set (...). +Loki saves the trouble of maintaining a sorted vector by hand by defining an AssocVector class +template. AssocVector is a drop-in replacement for std::map (it supports the same set of member +functions), implemented on top of std::vector. AssocVector differs from a map in the behavior of +its erase functions (AssocVector::erase invalidates all iterators into the object) and in the +complexity guarantees of insert and erase (linear as opposed to constant). ]] + +[*Boost.Container] `flat_[multi]map/set` containers are ordered-vector based associative containers +based on Austern's and Alexandrescu's guidelines. These ordered vector containers have also +benefited recently with the addition of `move semantics` to C++, speeding up insertion +and erasure times considerably. Flat associative containers have the following +attributes: + +* Faster lookup than standard associative containers +* Much faster iteration than standard associative containers +* Less memory consumption for small objects (and for big objects if `shrink_to_fit` is used) +* Improved cache performance (data is stored in contiguous memory) +* Non-stable iterators (iterators are invalidated when inserting and erasing elements) +* Non-copyable and non-movable values types can't be stored +* Weaker exception safety than standard associative containers +(copy/move constructors can throw when shifting values in erasures and insertions) +* Slower insertion and erasure than standard associative containers (specially for non-movable types) + +[endsect] + +[section:slist ['slist]] + +When the standard template library was designed, it contained a singly linked list called `slist`. +Unfortunately, this container was not standardized and remained as an extension for many standard +library implementations until C++11 introduced `forward_list`, which is a bit different from the +the original SGI `slist`. According to [@http://www.sgi.com/tech/stl/Slist.html SGI STL documentation]: + +["['An `slist` is a singly linked list: a list where each element is linked to the next element, but +not to the previous element. That is, it is a Sequence that supports forward but not backward traversal, +and (amortized) constant time insertion and removal of elements. Slists, like lists, have the important +property that insertion and splicing do not invalidate iterators to list elements, and that even removal +invalidates only the iterators that point to the elements that are removed. The ordering of iterators +may be changed (that is, slist::iterator might have a different predecessor or successor after a list +operation than it did before), but the iterators themselves will not be invalidated or made to point to +different elements unless that invalidation or mutation is explicit.]] + +["['The main difference between `slist` and list is that list's iterators are bidirectional iterators, +while slist's iterators are forward iterators. This means that `slist` is less versatile than list; +frequently, however, bidirectional iterators are unnecessary. You should usually use `slist` unless +you actually need the extra functionality of list, because singly linked lists are smaller and faster +than double linked lists.]] + +["['Important performance note: like every other Sequence, `slist` defines the member functions insert and erase. +Using these member functions carelessly, however, can result in disastrously slow programs. The problem is that +insert's first argument is an iterator pos, and that it inserts the new element(s) before pos. This means that +insert must find the iterator just before pos; this is a constant-time operation for list, since list has +bidirectional iterators, but for `slist` it must find that iterator by traversing the list from the beginning +up to pos. In other words: insert and erase are slow operations anywhere but near the beginning of the slist.]] + +["['Slist provides the member functions insert_after and erase_after, which are constant time operations: you should +always use insert_after and erase_after whenever possible. If you find that insert_after and erase_after aren't +adequate for your needs, and that you often need to use insert and erase in the middle of the list, then you +should probably use list instead of slist.]] + +[*Boost.Container] updates the classic `slist` container with C++11 features like move semantics and placement +insertion and implements it a bit differently for the standard C++11 `forward_list`. `forward_list` has no `size()` +method, so it's been designed to allow (or in practice, encourage) implementations without tracking list size +with every insertion/erasure, allowing constant-time +`splice_after(iterator, forward_list &, iterator, iterator)`-based list merging. On the other hand `slist` offers +constant-time `size()` for those that don't care about linear-time `splice_after(iterator, slist &, iterator, iterator)` +`size()` and offers an additional `splice_after(iterator, slist &, iterator, iterator, size_type)` method that +can speed up `slist` merging when the programmer already knows the size. `slist` and `forward_list` are therefore +complementary. + +[endsect] + +[endsect] + +[section:Cpp11_conformance C++11 Conformance] + +[*Boost.Container] aims for full C++11 conformance except reasoned deviations, +backporting as much as possible for C++03. Obviously, this conformance is a work +in progress so this section explains what C++11 features are implemented and which of them +have been backported to C++03 compilers. + +[section:move_emplace Move and Emplace] + +For compilers with rvalue references and for those C++03 types that use +[@http://www.boost.org/libs/move Boost.Move] rvalue reference emulation +[*Boost.Container] supports all C++11 features related to move semantics: containers +are movable, requirements for `value_type` are those specified for C++11 containers. + +For compilers with variadic templates, [*Boost.Container] supports placement insertion +(`emplace`, ...) functions from C++11. For those compilers without variadic templates +support [*Boost.Container] uses the preprocessor to create a set of overloads up to +a finite (10) number of parameters. + +[endsect] + +[section:alloc_traits_move_traits Stateful allocators and Scoped allocators] + +C++03 was not stateful-allocator friendly. For compactness of container objects and for +simplicity, it did not require containers to support allocators with state: Allocator objects +need not be stored in container objects. It was not possible to store an allocator with state, +say an allocator that holds a pointer to an arena from which to allocate. C++03 allowed implementors +to suppose two allocators of the same type always compare equal (that means that memory allocated +by one allocator object could be deallocated by another instance of the same type) and +allocators were not swapped when the container was swapped. + +Many C++ container implementors felt C++03 guarantees were too weak and started to offer extensions. +[*Boost.Container], following [@http://www.boost.org/libs/interprocess/ Boost.Interprocess] +containers experience supporting stateful allocators, offers the following guarantees: + +* Allocators are copy-constructed in copy/move constructors +* If possible, a single allocator is hold to construct `value_type` and this allocator is copy constructed + from the user-supplied allocator object during container's constructor. If the container needs an auxiliary + allocator (e.g. a array allocator used by `deque` or `stable_vector`), that allocator is also + copy-constructed from the user-supplied allocator when the container is constructed (i.e. it's + not constructed on the fly when auxiliary memory is needed). +* Allocators are compared for equality when swapping containers. If allocators don't compare + equal allocators are swapped using an unqualified `swap` call. + +C++11 further improves stateful allocator support through the +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2554.pdf +Scoped Allocators model], using classes like `std::scoped_allocator_adaptor` and `std::allocator_traits`. +[*Boost.Container does not support it yet, but there are plans to do so and backport scoped allocator +support to C++03 compilers. + +[endsect] + +[section:initializer_lists Initializer lists] + +[*Boost.Container] does not support initializer lists when constructing or assigning containers +but it will support it for compilers with initialized-list support. This feature won't be backported +to C++03 compilers. + +[endsect] + +[section:Vector_bool vector] + +`vector` specialization has been quite problematic, and there have been several +unsuccessful tries to deprecate or remove it from the standard. [*Boost.Container] does not implement it +as there is a superior [@http://www.boost.org/libs/dynamic_bitset/ Boost.DynamicBitset] +solution. For issues with `vector` see papers +[@http://www.gotw.ca/publications/N1211.pdf vector: N1211: More Problems, Better Solutions], +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2160.html N2160: Library Issue 96: Fixing vector], +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2204.html N2204 A Specification to deprecate vector]. + +* ["['In 1998, admitting that the committee made a mistake was controversial. + Since then Java has had to deprecate such significant portions of their libraries + that the idea C++ would be ridiculed for deprecating a single minor template specialization seems quaint.]] + +* ["['`vector` is not a container and `vector::iterator` is not a random-access iterator +(or even a forward or bidirectional iterator either, for that matter). This has already broken user code +in the field in mysterious ways.]] + +* ["['`vector` forces a specific (and potentially bad) optimization choice on all users by enshrining +it in the standard. The optimization is premature; different users have different requirements. This too +has already hurt users who have been forced to implement workarounds to disable the 'optimization' +(e.g., by using a vector and manually casting to/from bool).]] + +So `boost::container::vector::iterator` returns real `bool` references and works as a fully compliant container. +If you need a memory optimized version of `boost::container::vector` functionalities, please use +[@http://www.boost.org/libs/dynamic_bitset/ Boost.DynamicBitset]. + +[endsect] + +[endsect] + +[section:other_features Other features] + +* Default constructors don't allocate memory which improves performance and + usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw). + +* Small string optimization for [classref boost::container::basic_string basic_string], + with an internal buffer of 11/23 bytes (32/64 bit systems) + [*without] increasing the usual `sizeof` of the string (3 words). + +* `[multi]set/map` containers are size optimized embedding the color bit of the red-black tree nodes + in the parent pointer. + +* `[multi]set/map` containers use no recursive functions so stack problems are avoided. + +[endsect] + +[section:history_and_reasons History and reasons to use Boost.Container] + +[section:boost_container_history Boost.Container history] + +[*Boost.Container] is a product of a long development effort that started +[@http://lists.boost.org/Archives/boost/2004/11/76263.php in 2004 with the experimental Shmem library], +which pioneered the use of standard containers in shared memory. Shmem included modified SGI STL container +code tweaked to support non-raw `allocator::pointer` types and stateful allocators. Once reviewed, +Shmem was accepted as [@http://www.boost.org/libs/interprocess/ Boost.Interprocess] and this library +continued to refine and improve those containers. + +In 2007, container code from node containers (`map`, `list`, `slist`) was rewritten, refactored +and expanded to build the intrusive container library [@http://www.boost.org/libs/intrusive/ Boost.Intrusive]. +[*Boost.Interprocess] containers were refactored to take advantage of [*Boost.Intrusive] containers and +code duplication was minimized. Both libraries continued to gain support and bug fixes for years. +They introduced move semantics, emplacement insertion and more features of then unreleased C++0x +standard. + +[*Boost.Interprocess] containers were always standard compliant, and those containers and new +containers like `stable_vector` and `flat_[multi]set/map` were used outside [*Boost.Interprocess] +with success. As containers were mature enough to get their own library, it was a natural step to +collect them containers and build [*Boost.Container], a library targeted to a wider audience. + +[endsect] + + +[section:Why_boost_container Why Boost.Container?] + +With so many high quality standard library implementations out there, why would you want to +use [*Boost.Container]? There are several reasons for that: + +* If you have a C++03 compiler, you can have access to C++11 features and have an easy + code migration when you change your compiler. +* It's compatible with [*Boost.Interprocess] shared memory allocators. +* You have extremely useful new containers like `stable_vector` and `flat_[multi]set/map`. +* If you work on multiple platforms, you'll have a portable behaviour without depending + on the std-lib implementation conformance of each platform. Some examples: + * Default constructors don't allocate memory at all, which improves performance and + usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw). + * Small string optimization for [classref boost::container::basic_string basic_string]. +* New extensions beyond the standard based on user feedback to improve code performance. + +[endsect] + +[endsect] + +[include auto_index_helpers.qbk] + +[section:index Indexes] + +[named_index class_name Class Index] +[named_index typedef_name Typedef Index] +[named_index function_name Function Index] +[/named_index macro_name Macro Index] +[/index] + +[endsect] + +[xinclude autodoc.xml] + +[section:acknowledgements_notes Acknowledgements, notes and links] + +* Original standard container code comes from [@http://www.sgi.com/tech/stl/ SGI STL library], + which enhanced the original HP STL code. Most of this code was rewritten for + [*Boost.Interprocess] and moved to [*Boost.Intrusive]. `deque` and `string` containers still + have fragments of the original SGI code. Many thanks to Alexander Stepanov, Meng Lee, David Musser, + Matt Austern... and all HP and SGI STL developers. + +* `flat_[multi]_map/set` containers were originally based on [@http://en.wikipedia.org/wiki/Loki_%28C%2B%2B%29 Loki's] + AssocVector class. Code was rewritten and expanded for [*Boost.Interprocess], so thanks to Andrei Alexandrescu. + +* `stable_vector` was invented and coded by + [@http://bannalia.blogspot.com/2008/09/introducing-stablevector.html Joaqu\u00EDn M. L\u00F3pez Mu\u00F1oz], + then adapted for [*Boost.Interprocess]. Thanks for such a great container. + +* Howard Hinnant's help and advices were essential when implementing move semantics, + improving allocator support or implementing small string optimization. Thanks Howard + for your wonderful standard library implementations. + +* And finally thanks to all Boosters who helped all these years, improving, fixing and + reviewing all my libraries. + +[endsect] + +[section:release_notes Release Notes] + +* First release with Boost 1.48. Container code from [*Boost.Interprocess] was deleted + and redirected to [*Boost.Container ] via using directives. + +[endsect] diff --git a/doc/html/boostbook.css b/doc/html/boostbook.css new file mode 100644 index 0000000..2146334 --- /dev/null +++ b/doc/html/boostbook.css @@ -0,0 +1,537 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + + Use, modification and distribution is subject to 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) +=============================================================================*/ + +/*============================================================================= + Body defaults +=============================================================================*/ + + body + { + margin: 1em; + font-family: sans-serif; + } + +/*============================================================================= + Paragraphs +=============================================================================*/ + + p + { + text-align: left; + font-size: 10pt; + line-height: 1.15; + } + +/*============================================================================= + Program listings +=============================================================================*/ + + /* Code on paragraphs */ + p tt.computeroutput + { + font-size: 10pt; + } + + pre.synopsis + { + font-size: 10pt; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + .programlisting, + .screen + { + font-size: 10pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + +/*============================================================================= + Headings +=============================================================================*/ + + h1, h2, h3, h4, h5, h6 + { + text-align: left; + margin: 1em 0em 0.5em 0em; + font-weight: bold; + } + + h1 { font: 140% } + h2 { font: bold 140% } + h3 { font: bold 130% } + h4 { font: bold 120% } + h5 { font: italic 110% } + h6 { font: italic 100% } + + /* Top page titles */ + title, + h1.title, + h2.title + h3.title, + h4.title, + h5.title, + h6.title, + .refentrytitle + { + font-weight: bold; + margin-bottom: 1pc; + } + + h1.title { font-size: 140% } + h2.title { font-size: 140% } + h3.title { font-size: 130% } + h4.title { font-size: 120% } + h5.title { font-size: 110% } + h6.title { font-size: 100% } + + .section h1 + { + margin: 0em 0em 0.5em 0em; + font-size: 140%; + } + + .section h2 { font-size: 140% } + .section h3 { font-size: 130% } + .section h4 { font-size: 120% } + .section h5 { font-size: 110% } + .section h6 { font-size: 100% } + + /* Code on titles */ + h1 tt.computeroutput { font-size: 140% } + h2 tt.computeroutput { font-size: 140% } + h3 tt.computeroutput { font-size: 130% } + h4 tt.computeroutput { font-size: 120% } + h5 tt.computeroutput { font-size: 110% } + h6 tt.computeroutput { font-size: 100% } + +/*============================================================================= + Author +=============================================================================*/ + + h3.author + { + font-size: 100% + } + +/*============================================================================= + Lists +=============================================================================*/ + + li + { + font-size: 10pt; + line-height: 1.3; + } + + /* Unordered lists */ + ul + { + text-align: left; + } + + /* Ordered lists */ + ol + { + text-align: left; + } + +/*============================================================================= + Links +=============================================================================*/ + + a + { + text-decoration: none; /* no underline */ + } + + a:hover + { + text-decoration: underline; + } + +/*============================================================================= + Spirit style navigation +=============================================================================*/ + + .spirit-nav + { + text-align: right; + } + + .spirit-nav a + { + color: white; + padding-left: 0.5em; + } + + .spirit-nav img + { + border-width: 0px; + } + +/*============================================================================= + Table of contents +=============================================================================*/ + + .toc + { + margin: 1pc 4% 0pc 4%; + padding: 0.1pc 1pc 0.1pc 1pc; + font-size: 10pt; + line-height: 1.15; + } + + .toc-main + { + width: 600; + text-align: center; + margin: 1pc 1pc 1pc 10%; + padding: 2pc 1pc 3pc 1pc; + line-height: 0.1; + } + + .boost-toc + { + float: right; + padding: 0.5pc; + } + +/*============================================================================= + Tables +=============================================================================*/ + + .table-title, + div.table p.title + { + margin-left: 4%; + padding-right: 0.5em; + padding-left: 0.5em; + } + + .informaltable table, + .table table + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + div.informaltable table, + div.table table + { + padding: 4px; + } + + /* Table Cells */ + div.informaltable table tr td, + div.table table tr td + { + padding: 0.5em; + text-align: left; + } + + div.informaltable table tr th, + div.table table tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 120%; + } + +/*============================================================================= + Blurbs +=============================================================================*/ + + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + font-size: 10pt; + line-height: 1.2; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + p.blurb img + { + padding: 1pt; + } + +/*============================================================================= + Variable Lists +=============================================================================*/ + + span.term + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist table tbody tr td + { + text-align: left; + vertical-align: top; + padding: 0em 2em 0em 0em; + font-size: 10pt; + } + + div.variablelist table tbody tr td p + { + margin: 0em 0em 0.5em 0em; + } + + /* Make the terms in definition lists bold */ + div.variablelist dl dt + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist dl dd + { + margin: 1em 0em 1em 2em; + font-size: 10pt; + } + +/*============================================================================= + Misc +=============================================================================*/ + + /* Title of books and articles in bibliographies */ + span.title + { + font-style: italic; + } + + span.underline + { + text-decoration: underline; + } + + span.strikethrough + { + text-decoration: line-through; + } + + /* Copyright, Legal Notice */ + div div.legalnotice p + { + font-size: 8pt; + text-align: left + } + +/*============================================================================= + Colors +=============================================================================*/ + + @media screen + { + /* Links */ + a + { + color: #0C7445; + } + + a:visited + { + color: #663974; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, + h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, + h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited + { + text-decoration: none; /* no underline */ + color: #000000; + } + + /* Syntax Highlighting */ + .keyword { color: #0000AA; } + .identifier { color: #000000; } + .special { color: #707070; } + .preprocessor { color: #402080; } + .char { color: teal; } + .comment { color: #800000; } + .string { color: teal; } + .number { color: teal; } + .white_bkd { background-color: #E8FBE9; } + .dk_grey_bkd { background-color: #A0DAAC; } + + /* Copyright, Legal Notice */ + .copyright + { + color: #666666; + font-size: small; + } + + div div.legalnotice p + { + color: #666666; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + .programlisting, + .screen + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Blurbs */ + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + div.informaltable table tr th, + div.table table tr th + { + background-color: #E3F9E4; + border: 1px solid #DCDCDC; + } + + /* Misc */ + span.highlight + { + color: #00A000; + } + } + + @media print + { + /* Links */ + a + { + color: black; + } + + a:visited + { + color: black; + } + + .spirit-nav + { + display: none; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid gray; + background-color: #FAFFFB; + } + + .programlisting, + .screen + { + border: 1px solid gray; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + .informaltable table, + .table table + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + border-collapse: collapse; + background-color: #FAFFFB; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + div.informaltable table tr th, + div.table table tr th + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + /* Misc */ + span.highlight + { + font-weight: bold; + } + } diff --git a/doc/html/images/blank.png b/doc/html/images/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..764bf4f0c3bb4a09960b04b6fa9c9024bca703bc GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4kiW$2A`O3a~K#HSkfJR9T^xl_H+M9WMyDr z)b(_645^s&_M)R8g96V1g9H1Y`?|@Qa8+HmHda4(nQ?zM!!?FAj1kNm*b;aTNHv%; cj9>w=gf!;AOne?`3=9kmp00i_>zopr0Be8NW(e>Jab;j&;NV~o5MYpy zU{F+KFf?Rva$<;zVn|MA$j)XcE@r5%W@u?)XlW_#>0#*UDemd%nKFf8%9P?MQ>y38 zVVEwkZjIWyHF@jSt$X(}?A@Du?i|Cp zbLXyIW4Lzh+_h`h?%iX!chB(NJdh*`E$$X&!4}4&+z{J`|sZwzJC|^ z{$1kxcf;@BzyJTw@c+NS|Nj#IN5NBISn~R-X--a%afBxQ|J!3zMjr_SU zk_iHr)f*lf{$5^Qz}I)@3FlWvw(w~u=1P@VsTP+$RNGvxbHL-(%M6nc6`{zlU zjGQJeveps+!&Jb&mD)L@hA} z1_tL6*NBqf{Irtt#G+IN2MuLS&)mfHRNut(%;anZ6Fnn63k6F{eFF=914D)6qRirw zN{8Ia;*!i{z0_j8l+uFyyb`_S{M?DV6n8K%Fld2|%S_KpEGaEYWk@zRFt#waFg8d` zG)YZPF-fe)lBATd3a!N{b-$VA&f+n^|#(~yCI Ofx*+&&t;ucLK6T%G-N*j literal 0 HcmV?d00001 diff --git a/doc/html/images/draft.png b/doc/html/images/draft.png new file mode 100644 index 0000000000000000000000000000000000000000..0084708c9b8287c51efa6b40b8d492854191455e GIT binary patch literal 17454 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 YsPxZ;53A2HFfcH9y85}Sb4q9e0Fi|iga7~l literal 0 HcmV?d00001 diff --git a/doc/html/images/home.png b/doc/html/images/home.png new file mode 100644 index 0000000000000000000000000000000000000000..5584aacb097a80e66a5320312b6e4eb017af1a06 GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&Dfg?(A@OuseF>a6(*+nzF*onKLh6zO-%YmOy{sw6wJU|Nk%gvq74Hfq|za z$S?Rm0x$^OKX;CSfq}EYBeIx*fm;ZK886+f`@_J%pjzS@Q4*Y=R#Ki=l*-_nm|T>f zo0^iDsNj}alvU8YOY t9}F9JU6`43jMG5vNQA&8NcoN_f;wr$vARr(hAt9lu zscC6x>EvV>6{VS+EaBwj6ciMco$ZvI98_E!l$@NLot<4>UER|o(bHqOcQ41TYc{y!?kM?_wFg)yJvXsp5^oB z9Pi&Vyniq7|3Ab3{~Z7S3p{_W`TV)z`}cpO z$(;G%_wGG* z?AW<;=dNA5cJJQ3=g*(NfB*jb_wWDz|6hCQ@I3|w2F4_BcNgdM3%p4T42R|DNig) zWpL0?*7VFxOi%SqOwUZtRxr^s(z8&owA44S&^IttNG{4OE~#|Ltt>9dOx8;+)=McZ z$j>X$OU}=oxJz*d0|SE=*tpE}yu^~yqEv=t literal 0 HcmV?d00001 diff --git a/doc/html/images/next.png b/doc/html/images/next.png new file mode 100644 index 0000000000000000000000000000000000000000..59800b4e87f60c0e3383ede2b384b9be0f5ffe8d GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&Dfg?(8r&Hr}>%OQ656nzF)*4nJa0`Jj)#l9-t%+}PK^d+g590~2^trx_V+aGYt)W#Kgko@Q{~>i6>w}LxPb)_bi1gN;4a>^d{wcuv&t)U99M06BF~bt=lC3t1z!y3OU-_; z>3=1k>J3(3i_72APIz-IDqpqc+E%+vGv;(%KfZ!%@4A+C&xmZ75-RagX8L}A{%x+r zX<~gz))PX{awr=ezabJ<%O$qq%HpE?3}IarYhrI#g}e)4`)(-lYr?KO{@fm?UzpsD z&F7x?_G;CcbIZ>^o0GCAMe@{JfwtZgS9s0dn=t$|`IrrC3yU6#%a-U6G$wZz0 z>m`@($9HNPdGJ4#pEvb;3eT@>Ck6%v=MvY5lHmNblJdl&R0anPWlhiA#Pn3(#PrPM zYy}fNBRvZROG|wN3w;Aah2)~l;*v^-+{)sT%w)aPV!f2og8aM^z2yAdiMtecFfcG^ zfsM;d&r2*RElOoDPD(L1F;6y4H8Hg?FgGwTOER!DNJ%kHHBU4$OExhPxjgw70|Nse jNLN5&dMbmFNrjP#wt==mQ8cF^C=xwg{an^LB{Ts5w*0vf literal 0 HcmV?d00001 diff --git a/doc/html/images/prev.png b/doc/html/images/prev.png new file mode 100644 index 0000000000000000000000000000000000000000..d88a40f923e3c554125f01cd366707c60cfcad04 GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?WS z3GfMV6&DdqOG`60Hr}>%%ZlYo1O0u~loc*tzSP~>;p||S5Et|R|Noh1c$yg)73T~N2spa`a*~JRJ5eh~I1}5!gYtAz;Fo=OPI2WZRmSpDVDTHL^rZN~B=o=X8 z8<-ql-^0nkz!2u?;uumfC;0|1OPoRyGxLNShYX~Tl_Wf9G1_imu)%RA9}mw<0X2^e zQioc&m}WXSvRw^OFi2qFa&lm1W^U?K=~^Ook|m{hVvche^Q6-g?(V)Vn8U=toEqFE UkjD9gfq{X+)78&qol`;+00?PtqyPW_ literal 0 HcmV?d00001 diff --git a/doc/html/images/stable_vector.png b/doc/html/images/stable_vector.png new file mode 100644 index 0000000000000000000000000000000000000000..26af7af6d86dbb3d2e843003ef8d5f3807fc92e8 GIT binary patch literal 7163 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 CFT|e! literal 0 HcmV?d00001 diff --git a/doc/html/images/tip.png b/doc/html/images/tip.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4aab3bb3543191c360387c4af9a3cbaa051345 GIT binary patch literal 449 zcmeAS@N?(olHy`uVBq!ia0y~yV31^BV36QoU|?X-y2mNSz`($iDJ87yAgr${wU6ATeb^ycE^w7cIp z?_W?xU6%d(bb~@Shbi-aG=ETBbm~(ogOmrW&bwBIxdt+K+A3yD;V_t}R>0LF5GN)x zed{W(mq$!1ciVpPy1}W+9bm)Xrgda~bSbG?a3DdjluYV+O9SdLnMpASqX+9EZY3c7C@7#N&OTq83NAIrA4U>si~GJ7Ut&0mS)MRMrP)TsYwQg=9VeOrfC+2Nk)mu rLdL(;85kJ&K)M1F(^DCYOe>5`v<1B4~iR4S3j3^P6tl1hi%%HopDWWCg4y_C{| z{JavqiARt`YJFJnVhX)qGzOMplv!L->5yAl zT#}irms+fsQd*FoSE84kpF44v;tmD|1}(60ndy0nC8b5F42emG<`xDZ$;L?r7Ky3J=GDKJX@I;2(iM=Hp2}coT4AYeplx7Y_5oxZgQu&X%Q~lo FCIGT9P(J_w literal 0 HcmV?d00001 diff --git a/doc/html/images/up.png b/doc/html/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..17d9c3ec491ae1ba22188ce85985623c92ffa9be GIT binary patch literal 370 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj7G?$phK4%r{|pQa%*9TgAsieWw;%dHU|?X- z3h)VW6&DdqOG|Thu-mqE%ZlYoyE{8BU%nLR@2jS)FmvY2qel)W#Kk;%^zi@x|I?Un z*fKCM@RbDl1^-6|46X<6oM2#J;4JWnEM{Qf76M_$OLy!3FfcHvmbgZg1m~xflqVLY zGWaGY7v<-srer26xMdclmgg5`7c2NiC>R+Sn6#IzInThrAO_OlT$Gwvl9`{U5R#dj z%3x@qZ(yu%U~+tY4<`cyLy@P8V@SoEspmFwHW&!FJyeg_(XezvV9WvAI|r@_>dZZG zPW6aiOT!J--9O?NG0%AP;}ge|4lDQN4=-}8`?JGwx}?mMnO)OdyQdu$nQCjPRV}jm z$u!Qa8E-cQ-r3Nz>Y(YPTd#BPEH+&8GWqfD!}4*53%dA!%#3$cIv;a~fq{X+)78&q Iol`;+0POUaApigX literal 0 HcmV?d00001 diff --git a/doc/html/images/warning.png b/doc/html/images/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..1c33db8f34a8b42b373179b46a2d8d8a10e061a9 GIT binary patch literal 1241 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8NW(e>JaphoO5CF?5GB9W| zFc>m0I59AIF)#!%FhnshWHT@nGcZ&$Ftji*^e`|?VPKe2T|Fl#Xiikroa*YO3=B&x zEth(EEp2I8I%UezrAyZ`FswB+TsvjTRtAQxnwndCdbZA)vvujxty{P5WnkF5cJ1D+ zTaPg?91{>YCLwX`*s*gA4Ce#{&Phm|)6~4iz;I1d^V+p*_ZS%N-Mjakf#JEL;`8Uv z-!m}0=iqq%{{43bhVS3M|7T$MKMF=efJz}yVEuRs0|NtNlDE4HLkFv@2Ll7c3r`ov zkcwNmlWOyu3izvS7ejxP>R-!INP5f(XN|IS^C^Iyp?`SUk1vQO?s(K&l| zi|Nkt0@~*ymDp65*E-HED6u(s{Mfrxmah{JrgAMTIq)Du?nC5nnYTRgThA|azEdIl zD^uvV>~q(b?>`Fd;xnAbe7so1I$-&keKN}|vNNOCvX<~g{)wp7{&hR__v^cBU*Gq* zV3YS!cBPWsl#eNWc|~nAXWMOB8tQWBuXo=4>}cytyX_5F^Az{bVJ>7~U~n#RjVKAu zPb(=;EJ|f?&`{R&%uP&B^-WCAOwLv?(KFJsP_VSrH?Yt*FjPn`$}BFabjYnNF3C*R zOD)z*DJ{s)E742N&z-nSaR&nfgBIAh%=Em(lG377hGY|?B=Z!b6jL*k#Ka_13kwTN zLrZf@a|7cv1EVApQ-8txlNlHo_&~Y>64O%|j7%zwOtcNO4T_>U4H+017(8A5T-G@y GGywozG)2h( literal 0 HcmV?d00001 diff --git a/doc/html/reference.css b/doc/html/reference.css new file mode 100644 index 0000000..1bf6b68 --- /dev/null +++ b/doc/html/reference.css @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + + Use, modification and distribution is subject to 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) +=============================================================================*/ +PRE.synopsis { + background-color: #e0ffff; + border: thin solid blue; + padding: 1em +} diff --git a/doc/index.idx b/doc/index.idx new file mode 100644 index 0000000..9d0d126 --- /dev/null +++ b/doc/index.idx @@ -0,0 +1 @@ +!scan-path "boost/container" ".*.hpp" false diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 new file mode 100644 index 0000000..1b4eb2d --- /dev/null +++ b/example/Jamfile.v2 @@ -0,0 +1,34 @@ +# Boost Container Library Example Jamfile + +# (C) Copyright Ion Gaztanaga 2009 +# Use, modification and distribution are subject to 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) + +# Adapted from John Maddock's TR1 Jamfile.v2 +# Copyright John Maddock 2005. +# Use, modification and distribution are subject to 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 rule enumerates through all the sources and invokes +# the run rule for each source, the result is a list of all +# the run rules, which we can pass on to the test_suite rule: + +rule test_all +{ + local all_rules = ; + + for local fileb in [ glob doc_*.cpp ] + { + all_rules += [ run $(fileb) + : # additional args + : # test-files + : # requirements + ] ; + } + + return $(all_rules) ; +} + +test-suite container_example : [ test_all r ] : multi ; \ No newline at end of file diff --git a/example/doc_emplace.cpp b/example/doc_emplace.cpp new file mode 100644 index 0000000..68e4a66 --- /dev/null +++ b/example/doc_emplace.cpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_emplace +#include +#include + +//Non-copyable and non-movable class +class non_copy_movable +{ + non_copy_movable(const non_copy_movable &); + non_copy_movable& operator=(const non_copy_movable &); + + public: + non_copy_movable(int = 0) {} +}; + +int main () +{ + using namespace boost::container; + + //Store non-copyable and non-movable objects in a list + list l; + non_copy_movable ncm; + + //A new element will be built calling non_copy_movable(int) contructor + l.emplace(l.begin(), 0); + assert(l.size() == 1); + + //A new element will be built calling the default constructor + l.emplace(l.begin()); + assert(l.size() == 2); + return 0; +} +//] +#include diff --git a/example/doc_move_containers.cpp b/example/doc_move_containers.cpp new file mode 100644 index 0000000..02e037c --- /dev/null +++ b/example/doc_move_containers.cpp @@ -0,0 +1,54 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_move_containers +#include +#include +#include + +//Non-copyable class +class non_copyable +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(non_copyable) + + public: + non_copyable(){} + non_copyable(BOOST_RV_REF(non_copyable)) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable)) { return *this; } +}; + +int main () +{ + using namespace boost::container; + + //Store non-copyable objects in a vector + vector v; + non_copyable nc; + v.push_back(boost::move(nc)); + assert(v.size() == 1); + + //Reserve no longer needs copy-constructible + v.reserve(100); + assert(v.capacity() >= 100); + + //This resize overload only needs movable and default constructible + v.resize(200); + assert(v.size() == 200); + + //Containers are also movable + vector v_other(boost::move(v)); + assert(v_other.size() == 200); + assert(v.empty()); + + return 0; +} +//] +#include diff --git a/example/doc_recursive_containers.cpp b/example/doc_recursive_containers.cpp new file mode 100644 index 0000000..b184d19 --- /dev/null +++ b/example/doc_recursive_containers.cpp @@ -0,0 +1,61 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_recursive_containers +#include +#include +#include +#include +#include + +using namespace boost::container; + +struct data +{ + int i_; + //A vector holding still undefined class 'data' + vector v_; + //A list holding still undefined 'data' + list l_; + //A map holding still undefined 'data' + map m_; + + friend bool operator <(const data &l, const data &r) + { return l.i_ < r.i_; } +}; + +struct tree_node +{ + string name; + string value; + + //children nodes of this node + list children_; +}; + + + +int main() +{ + //a container holding a recursive data type + stable_vector sv; + sv.resize(100); + + //Let's build a tree based in + //a recursive data type + tree_node root; + root.name = "root"; + root.value = "root_value"; + root.children_.resize(7); + return 0; +} +//] +#include diff --git a/example/doc_type_erasure.cpp b/example/doc_type_erasure.cpp new file mode 100644 index 0000000..04dca80 --- /dev/null +++ b/example/doc_type_erasure.cpp @@ -0,0 +1,91 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_type_erasure_MyClassHolder_h +#include + +//MyClassHolder.h + +//We don't need to include "MyClass.h" +//to store vector +class MyClass; + +class MyClassHolder +{ + public: + + void AddNewObject(const MyClass &o); + const MyClass & GetLastObject() const; + + private: + ::boost::container::vector vector_; +}; + +//] + +//[doc_type_erasure_MyClass_h + +//MyClass.h + +class MyClass +{ + private: + int value_; + + public: + MyClass(int val = 0) : value_(val){} + + friend bool operator==(const MyClass &l, const MyClass &r) + { return l.value_ == r.value_; } + //... +}; + +//] + + + +//[doc_type_erasure_main_cpp + +//Main.cpp + +//=#include "MyClassHolder.h" +//=#include "MyClass.h" + +#include + +int main() +{ + MyClass mc(7); + MyClassHolder myclassholder; + myclassholder.AddNewObject(mc); + return myclassholder.GetLastObject() == mc ? 0 : 1; +} +//] + +//[doc_type_erasure_MyClassHolder_cpp + +//MyClassHolder.cpp + +//=#include "MyClassHolder.h" + +//In the implementation MyClass must be a complete +//type so we include the appropriate header +//=#include "MyClass.h" + +void MyClassHolder::AddNewObject(const MyClass &o) +{ vector_.push_back(o); } + +const MyClass & MyClassHolder::GetLastObject() const +{ return vector_.back(); } + +//] + +#include diff --git a/index.html b/index.html new file mode 100644 index 0000000..ad39f65 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + +Automatic redirection failed, please go to +../../doc/html/container.html + + diff --git a/proj/to-do.txt b/proj/to-do.txt new file mode 100644 index 0000000..c7f77cf --- /dev/null +++ b/proj/to-do.txt @@ -0,0 +1,2 @@ +->Change "insert" and "push_back"/"push_front" to catch non-const rvalues +->Add an example with stateful allocators diff --git a/proj/vc7ide/container.sln b/proj/vc7ide/container.sln new file mode 100644 index 0000000..ea29003 --- /dev/null +++ b/proj/vc7ide/container.sln @@ -0,0 +1,87 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deque_test", "deque_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792655}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_tree_test", "flat_tree_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792637}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list_test", "list_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792632}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stable_vector_test", "stable_vector_test.vcproj", "{5E11C8D3-FA52-760A-84FE-943A6BA05A21}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "string_test", "string_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D4A792607}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tree_test", "tree_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792606}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slist_test", "slist_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792608}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vector_test", "vector_test.vcproj", "{5CE11C83-096A-84FE-4FA2-D3A6BA792002}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_containerlib", "container.vcproj", "{FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.Build.0 = Release|Win32 + {5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Debug.ActiveCfg = Debug|Win32 + {5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Debug.Build.0 = Debug|Win32 + {5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Release.ActiveCfg = Release|Win32 + {5E11C8D3-FA52-760A-84FE-943A6BA05A21}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D4A792607}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D4A792607}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D4A792607}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D4A792607}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792608}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792608}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792608}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792608}.Release.Build.0 = Release|Win32 + {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.ActiveCfg = Debug|Win32 + {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.Build.0 = Debug|Win32 + {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.ActiveCfg = Release|Win32 + {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.Build.0 = Release|Win32 + {FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.ActiveCfg = Debug|Win32 + {FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Debug.Build.0 = Debug|Win32 + {FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.ActiveCfg = Release|Win32 + {FF56BAF1-32EC-4B22-B6BD-95A3A67C3135}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/proj/vc7ide/container.vcproj b/proj/vc7ide/container.vcproj new file mode 100644 index 0000000..500b5ca --- /dev/null +++ b/proj/vc7ide/container.vcproj @@ -0,0 +1,321 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/deque_test.vcproj b/proj/vc7ide/deque_test.vcproj new file mode 100644 index 0000000..b416a71 --- /dev/null +++ b/proj/vc7ide/deque_test.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/flat_tree_test.vcproj b/proj/vc7ide/flat_tree_test.vcproj new file mode 100644 index 0000000..4e05a16 --- /dev/null +++ b/proj/vc7ide/flat_tree_test.vcproj @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/list_ex.vcproj b/proj/vc7ide/list_ex.vcproj new file mode 100644 index 0000000..e3198de --- /dev/null +++ b/proj/vc7ide/list_ex.vcproj @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/slist_test.vcproj b/proj/vc7ide/slist_test.vcproj new file mode 100644 index 0000000..2e813bb --- /dev/null +++ b/proj/vc7ide/slist_test.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/stable_vector_test.vcproj b/proj/vc7ide/stable_vector_test.vcproj new file mode 100644 index 0000000..fdc2192 --- /dev/null +++ b/proj/vc7ide/stable_vector_test.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/string_test.vcproj b/proj/vc7ide/string_test.vcproj new file mode 100644 index 0000000..77f6f35 --- /dev/null +++ b/proj/vc7ide/string_test.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/tree_test.vcproj b/proj/vc7ide/tree_test.vcproj new file mode 100644 index 0000000..0231de2 --- /dev/null +++ b/proj/vc7ide/tree_test.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/vector_test.vcproj b/proj/vc7ide/vector_test.vcproj new file mode 100644 index 0000000..270f5cf --- /dev/null +++ b/proj/vc7ide/vector_test.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000..6120122 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,34 @@ +# Boost Container Library Test Jamfile + +# (C) Copyright Ion Gaztanaga 2009. +# Use, modification and distribution are subject to 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) + +# Adapted from John Maddock's TR1 Jamfile.v2 +# Copyright John Maddock 2005. +# Use, modification and distribution are subject to 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 rule enumerates through all the sources and invokes +# the run rule for each source, the result is a list of all +# the run rules, which we can pass on to the test_suite rule: + +rule test_all +{ + local all_rules = ; + + for local fileb in [ glob *.cpp ] + { + all_rules += [ run $(fileb) + : # additional args + : # test-files + : # requirements + ] ; + } + + return $(all_rules) ; +} + +test-suite container_test : [ test_all r ] ; diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp new file mode 100644 index 0000000..ccdfa45 --- /dev/null +++ b/test/check_equal_containers.hpp @@ -0,0 +1,76 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINERS_HPP +#define BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINERS_HPP + +#include +#include +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +//Function to check if both containers are equal +template +bool CheckEqualContainers(MyBoostCont *boostcont, MyStdCont *stdcont) +{ + if(boostcont->size() != stdcont->size()) + return false; + + typedef typename MyBoostCont::value_type value_type; + + typename MyBoostCont::iterator itboost(boostcont->begin()), itboostend(boostcont->end()); + typename MyStdCont::iterator itstd(stdcont->begin()); + typename MyStdCont::size_type dist = (typename MyStdCont::size_type)std::distance(itboost, itboostend); + if(dist != boostcont->size()){ + return false; + } + std::size_t i = 0; + for(; itboost != itboostend; ++itboost, ++itstd, ++i){ + value_type val(*itstd); + const value_type &v = *itboost; + if(v != val) + return false; + } + return true; +} + +template +bool CheckEqualPairContainers(MyBoostCont *boostcont, MyStdCont *stdcont) +{ + if(boostcont->size() != stdcont->size()) + return false; + + typedef typename MyBoostCont::key_type key_type; + typedef typename MyBoostCont::mapped_type mapped_type; + + typename MyBoostCont::iterator itboost(boostcont->begin()), itboostend(boostcont->end()); + typename MyStdCont::iterator itstd(stdcont->begin()); + for(; itboost != itboostend; ++itboost, ++itstd){ + if(itboost->first != key_type(itstd->first)) + return false; + + if(itboost->second != mapped_type(itstd->second)) + return false; + } + return true; +} +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINERS_HPP diff --git a/test/deque_test.cpp b/test/deque_test.cpp new file mode 100644 index 0000000..ad4b7ac --- /dev/null +++ b/test/deque_test.cpp @@ -0,0 +1,295 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "print_container.hpp" +#include "check_equal_containers.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include +#include +#include +#include +#include "emplace_test.hpp" +#include "vector_test.hpp" + + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +template class boost::container::deque + < test::movable_and_copyable_int + , test::dummy_test_allocator >; + +//Function to check if both sets are equal +template +bool deque_copyable_only(V1 *, V2 *, containers_detail::false_type) +{ + return true; +} + +//Function to check if both sets are equal +template +bool deque_copyable_only(V1 *cntdeque, V2 *stddeque, containers_detail::true_type) +{ + typedef typename V1::value_type IntType; + std::size_t size = cntdeque->size(); + stddeque->insert(stddeque->end(), 50, 1); + cntdeque->insert(cntdeque->end(), 50, 1); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + { + IntType move_me(1); + stddeque->insert(stddeque->begin()+size/2, 50, 1); + cntdeque->insert(cntdeque->begin()+size/2, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + { + IntType move_me(2); + cntdeque->assign(cntdeque->size()/2, boost::move(move_me)); + stddeque->assign(stddeque->size()/2, 2); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + { + IntType move_me(1); + stddeque->clear(); + cntdeque->clear(); + stddeque->insert(stddeque->begin(), 50, 1); + cntdeque->insert(cntdeque->begin(), 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + stddeque->insert(stddeque->begin()+20, 50, 1); + cntdeque->insert(cntdeque->begin()+20, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + stddeque->insert(stddeque->begin()+20, 20, 1); + cntdeque->insert(cntdeque->begin()+20, 20, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + { + IntType move_me(1); + stddeque->clear(); + cntdeque->clear(); + stddeque->insert(stddeque->end(), 50, 1); + cntdeque->insert(cntdeque->end(), 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + stddeque->insert(stddeque->end()-20, 50, 1); + cntdeque->insert(cntdeque->end()-20, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + stddeque->insert(stddeque->end()-20, 20, 1); + cntdeque->insert(cntdeque->end()-20, 20, boost::move(move_me)); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + + return true; +} + +//Test recursive structures +class recursive_deque +{ +public: + int id_; + deque deque_; +}; + +template +bool do_test() +{ + //Test for recursive types + { + deque recursive_deque_deque; + } + + { + //Now test move semantics + deque original; + deque move_ctor(boost::move(original)); + deque move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + + //Alias deque types + typedef deque MyCntDeque; + typedef std::deque MyStdDeque; + const int max = 100; + try{ + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyCntDeque *cntdeque = new MyCntDeque; + MyStdDeque *stddeque = new MyStdDeque; + //Compare several shared memory deque operations with std::deque + int i; + for(i = 0; i < max*100; ++i){ + IntType move_me(i); + cntdeque->insert(cntdeque->end(), boost::move(move_me)); + stddeque->insert(stddeque->end(), i); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + cntdeque->clear(); + stddeque->clear(); + + for(i = 0; i < max*100; ++i){ + IntType move_me(i); + cntdeque->push_back(boost::move(move_me)); + stddeque->push_back(i); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + cntdeque->clear(); + stddeque->clear(); + + for(i = 0; i < max*100; ++i){ + IntType move_me(i); + cntdeque->push_front(boost::move(move_me)); + stddeque->push_front(i); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + typename MyCntDeque::iterator it; + typename MyCntDeque::const_iterator cit = it; + + cntdeque->erase(cntdeque->begin()++); + stddeque->erase(stddeque->begin()++); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + cntdeque->erase(cntdeque->begin()); + stddeque->erase(stddeque->begin()); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + { + //Initialize values + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me (-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + + cntdeque->insert(cntdeque->end() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(aux_vect + 50)); + stddeque->insert(stddeque->end(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + for(int i = 0, j = static_cast(cntdeque->size()); i < j; ++i){ + cntdeque->erase(cntdeque->begin()); + stddeque->erase(stddeque->begin()); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + cntdeque->insert(cntdeque->begin() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(aux_vect + 50)); + stddeque->insert(stddeque->begin(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + } + + if(!deque_copyable_only(cntdeque, stddeque + ,containers_detail::bool_::value>())){ + return false; + } + + cntdeque->erase(cntdeque->begin()); + stddeque->erase(stddeque->begin()); + + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + for(i = 0; i < max; ++i){ + IntType move_me(i); + cntdeque->insert(cntdeque->begin(), boost::move(move_me)); + stddeque->insert(stddeque->begin(), i); + } + if(!test::CheckEqualContainers(cntdeque, stddeque)) return false; + + //Test insertion from list + { + std::list l(50, int(1)); + cntdeque->insert(cntdeque->begin(), l.begin(), l.end()); + stddeque->insert(stddeque->begin(), l.begin(), l.end()); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; + cntdeque->assign(l.begin(), l.end()); + stddeque->assign(l.begin(), l.end()); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; + } + + cntdeque->resize(100); + stddeque->resize(100); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; + + cntdeque->resize(200); + stddeque->resize(200); + if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1; + + delete cntdeque; + delete stddeque; + } + catch(std::exception &ex){ + std::cout << ex.what() << std::endl; + return false; + } + + std::cout << std::endl << "Test OK!" << std::endl; + return true; +} + + +int main () +{ + if(!do_test()) + return 1; + + if(!do_test()) + return 1; + + { + typedef deque MyDeque; + typedef deque MyMoveDeque; + typedef deque MyCopyMoveDeque; + typedef deque MyCopyDeque; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + } + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); + + if(!boost::container::test::test_emplace + < deque, Options>()) + return 1; + + return 0; +} + +#include diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp new file mode 100644 index 0000000..e03255e --- /dev/null +++ b/test/dummy_test_allocator.hpp @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP +#define BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an allocator to test expand capabilities + +namespace boost { +namespace container { +namespace test { + +//This allocator just allows two allocations. The first one will return +//mp_buffer + m_offset configured in the constructor. The second one +//will return mp_buffer. +template +class dummy_test_allocator +{ + private: + typedef dummy_test_allocator self_t; + typedef void * aux_pointer_t; + typedef const void * cvoid_ptr; + + template + dummy_test_allocator& operator=(const dummy_test_allocator&); + + dummy_test_allocator& operator=(const dummy_test_allocator&); + + public: + typedef T value_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef typename containers_detail::add_reference + ::type reference; + typedef typename containers_detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + +// typedef boost::container::version_type version; + + template + struct rebind + { typedef dummy_test_allocator other; }; + + //!Default constructor. Never throws + dummy_test_allocator() + {} + + //!Constructor from other dummy_test_allocator. Never throws + dummy_test_allocator(const dummy_test_allocator &) + {} + + //!Constructor from related dummy_test_allocator. Never throws + template + dummy_test_allocator(const dummy_test_allocator &) + {} + + pointer address(reference value) + { return pointer(addressof(value)); } + + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } + + pointer allocate(size_type, cvoid_ptr = 0) + { return 0; } + + void deallocate(const pointer &, size_type) + { } + + template + void construct(pointer, const Convertible &) + {} + + void destroy(pointer) + {} + + size_type max_size() const + { return 0; } + + friend void swap(self_t &, self_t &) + {} + + //Experimental version 2 dummy_test_allocator functions + + std::pair + allocation_command(boost::container::allocation_type, + size_type, + size_type, + size_type &, const pointer & = 0) + { return std::pair(pointer(0), true); } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. + size_type size(const pointer &) const + { return 0; } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::container::bad_alloc if there is no enough memory + pointer allocate_one() + { return pointer(0); } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &) + {} +}; + +//!Equality test for same type of dummy_test_allocator +template inline +bool operator==(const dummy_test_allocator &, + const dummy_test_allocator &) +{ return false; } + +//!Inequality test for same type of dummy_test_allocator +template inline +bool operator!=(const dummy_test_allocator &, + const dummy_test_allocator &) +{ return true; } + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP + diff --git a/test/emplace_test.hpp b/test/emplace_test.hpp new file mode 100644 index 0000000..3cae3f8 --- /dev/null +++ b/test/emplace_test.hpp @@ -0,0 +1,625 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP +#define BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +class EmplaceInt +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(EmplaceInt) + + public: + EmplaceInt(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0) + : a_(a), b_(b), c_(c), d_(d), e_(e) + {} + + EmplaceInt(BOOST_RV_REF(EmplaceInt) o) + : a_(o.a_), b_(o.b_), c_(o.c_), d_(o.d_), e_(o.e_) + {} + + EmplaceInt& operator=(BOOST_RV_REF(EmplaceInt) o) + { + this->a_ = o.a_; + this->b_ = o.b_; + this->c_ = o.c_; + this->d_ = o.d_; + this->e_ = o.e_; + return *this; + } + + friend bool operator==(const EmplaceInt &l, const EmplaceInt &r) + { + return l.a_ == r.a_ && + l.b_ == r.b_ && + l.c_ == r.c_ && + l.d_ == r.d_ && + l.e_ == r.e_; + } + + friend bool operator<(const EmplaceInt &l, const EmplaceInt &r) + { return l.sum() < r.sum(); } + + friend bool operator>(const EmplaceInt &l, const EmplaceInt &r) + { return l.sum() > r.sum(); } + + friend bool operator!=(const EmplaceInt &l, const EmplaceInt &r) + { return !(l == r); } + + friend std::ostream &operator <<(std::ostream &os, const EmplaceInt &v) + { + os << "EmplaceInt: " << v.a_ << ' ' << v.b_ << ' ' << v.c_ << ' ' << v.d_ << ' ' << v.e_; + return os; + } + + ~EmplaceInt() + { a_ = b_ = c_ = d_ = e_ = 0; } + + //private: + int sum() const + { return this->a_ + this->b_ + this->c_ + this->d_ + this->e_; } + + int a_, b_, c_, d_, e_; + int padding[6]; +}; + + +} //namespace test { + +namespace test { + +enum EmplaceOptions{ + EMPLACE_BACK = 1 << 0, + EMPLACE_FRONT = 1 << 1, + EMPLACE_BEFORE = 1 << 2, + EMPLACE_AFTER = 1 << 3, + EMPLACE_ASSOC = 1 << 4, + EMPLACE_HINT = 1 << 5, + EMPLACE_ASSOC_PAIR = 1 << 6, + EMPLACE_HINT_PAIR = 1 << 7 +}; + +template +bool test_expected_container(const Container &ec, const EmplaceInt *Expected, unsigned int only_first_n) +{ + typedef typename Container::const_iterator const_iterator; + const_iterator itb(ec.begin()), ite(ec.end()); + unsigned int cur = 0; + if(only_first_n > ec.size()){ + return false; + } + for(; itb != ite && only_first_n--; ++itb, ++cur){ + const EmplaceInt & cr = *itb; + if(cr != Expected[cur]){ + return false; + } + } + return true; +} + +template +bool test_expected_container(const Container &ec, const std::pair *Expected, unsigned int only_first_n) +{ + typedef typename Container::const_iterator const_iterator; + const_iterator itb(ec.begin()), ite(ec.end()); + unsigned int cur = 0; + if(only_first_n > ec.size()){ + return false; + } + for(; itb != ite && only_first_n--; ++itb, ++cur){ + if(itb->first != Expected[cur].first){ + std::cout << "Error in first: " << itb->first << ' ' << Expected[cur].first << std::endl; + return false; + + } + else if(itb->second != Expected[cur].second){ + std::cout << "Error in second: " << itb->second << ' ' << Expected[cur].second << std::endl; + return false; + } + } + return true; +} + +static EmplaceInt expected [10]; + +typedef std::pair EmplaceIntPair; +static boost::aligned_storage::type pair_storage; + +static EmplaceIntPair* initialize_emplace_int_pair() +{ + EmplaceIntPair* ret = reinterpret_cast(&pair_storage); + for(unsigned int i = 0; i != 10; ++i){ + new(&ret->first)EmplaceInt(); + new(&ret->second)EmplaceInt(); + } + return ret; +} + +static EmplaceIntPair * expected_pair = initialize_emplace_int_pair(); + + +template +bool test_emplace_back(containers_detail::true_) +{ + std::cout << "Starting test_emplace_back." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + Container c; + c.emplace_back(); + if(!test_expected_container(c, &expected[0], 1)) + return false; + c.emplace_back(1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace_back(1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + c.emplace_back(1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + c.emplace_back(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + c.emplace_back(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + + return true; +} + +template +bool test_emplace_back(containers_detail::false_) +{ return true; } + +template +bool test_emplace_front(containers_detail::true_) +{ + std::cout << "Starting test_emplace_front." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(1, 2, 3, 4, 5); + new(&expected [1]) EmplaceInt(1, 2, 3, 4); + new(&expected [2]) EmplaceInt(1, 2, 3); + new(&expected [3]) EmplaceInt(1, 2); + new(&expected [4]) EmplaceInt(1); + new(&expected [5]) EmplaceInt(); + Container c; + c.emplace_front(); + if(!test_expected_container(c, &expected[0] + 5, 1)) + return false; + c.emplace_front(1);/* + if(!test_expected_container(c, &expected[0] + 4, 2)) + return false; + c.emplace_front(1, 2); + if(!test_expected_container(c, &expected[0] + 3, 3)) + return false; + c.emplace_front(1, 2, 3); + if(!test_expected_container(c, &expected[0] + 2, 4)) + return false; + c.emplace_front(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0] + 1, 5)) + return false; + c.emplace_front(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0] + 0, 6)) + return false;*/ + } + return true; +} + +template +bool test_emplace_front(containers_detail::false_) +{ return true; } + +template +bool test_emplace_before(containers_detail::true_) +{ + std::cout << "Starting test_emplace_before." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(); + Container c; + c.emplace(c.cend(), 1); + c.emplace(c.cbegin()); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace(c.cend()); + if(!test_expected_container(c, &expected[0], 3)) + return false; + } + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + //emplace_front-like + Container c; + c.emplace(c.cbegin(), 1, 2, 3, 4, 5); + c.emplace(c.cbegin(), 1, 2, 3, 4); + c.emplace(c.cbegin(), 1, 2, 3); + c.emplace(c.cbegin(), 1, 2); + c.emplace(c.cbegin(), 1); + c.emplace(c.cbegin()); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_back-like + typename Container::const_iterator i = c.emplace(c.cend()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + i = c.emplace(++i, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + i = c.emplace(++i, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + i = c.emplace(++i, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + i = c.emplace(++i, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + i = c.emplace(++i, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace in the middle + c.emplace(c.cbegin()); + i = c.emplace(c.cend(), 1, 2, 3, 4, 5); + i = c.emplace(i, 1, 2, 3, 4); + i = c.emplace(i, 1, 2, 3); + i = c.emplace(i, 1, 2); + i = c.emplace(i, 1); + + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_before(containers_detail::false_) +{ return true; } + +template +bool test_emplace_after(containers_detail::true_) +{ + std::cout << "Starting test_emplace_after." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(); + Container c; + typename Container::const_iterator i = c.emplace_after(c.cbefore_begin(), 1); + c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace_after(i); + if(!test_expected_container(c, &expected[0], 3)) + return false; + } + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + //emplace_front-like + Container c; + c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4, 5); + c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4); + c.emplace_after(c.cbefore_begin(), 1, 2, 3); + c.emplace_after(c.cbefore_begin(), 1, 2); + c.emplace_after(c.cbefore_begin(), 1); + c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_back-like + typename Container::const_iterator i = c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + i = c.emplace_after(i, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + i = c.emplace_after(i, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + i = c.emplace_after(i, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + i = c.emplace_after(i, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + i = c.emplace_after(i, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_after in the middle + i = c.emplace_after(c.cbefore_begin()); + c.emplace_after(i, 1, 2, 3, 4, 5); + c.emplace_after(i, 1, 2, 3, 4); + c.emplace_after(i, 1, 2, 3); + c.emplace_after(i, 1, 2); + c.emplace_after(i, 1); + + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_after(containers_detail::false_) +{ return true; } + +template +bool test_emplace_assoc(containers_detail::true_) +{ + std::cout << "Starting test_emplace_assoc." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + { + Container c; + c.emplace(); + if(!test_expected_container(c, &expected[0], 1)) + return false; + c.emplace(1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace(1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + c.emplace(1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + c.emplace(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + c.emplace(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_assoc(containers_detail::false_) +{ return true; } + +template +bool test_emplace_hint(containers_detail::true_) +{ + std::cout << "Starting test_emplace_hint." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + + { + Container c; + typename Container::const_iterator it; + it = c.emplace_hint(c.begin()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + it = c.emplace_hint(it, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + it = c.emplace_hint(it, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + it = c.emplace_hint(it, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + it = c.emplace_hint(it, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + it = c.emplace_hint(it, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + + return true; +} + +template +bool test_emplace_hint(containers_detail::false_) +{ return true; } + +template +bool test_emplace_assoc_pair(containers_detail::true_) +{ + std::cout << "Starting test_emplace_assoc_pair." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected_pair[0].first) EmplaceInt(); + new(&expected_pair[0].second) EmplaceInt(); + new(&expected_pair[1].first) EmplaceInt(1); + new(&expected_pair[1].second) EmplaceInt(); + new(&expected_pair[2].first) EmplaceInt(2); + new(&expected_pair[2].second) EmplaceInt(2); + new(&expected_pair[3].first) EmplaceInt(3); + new(&expected_pair[3].second) EmplaceInt(2, 3); + new(&expected_pair[4].first) EmplaceInt(4); + new(&expected_pair[4].second) EmplaceInt(2, 3, 4); + new(&expected_pair[5].first) EmplaceInt(5); + new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5); + { + Container c; + c.emplace(); + if(!test_expected_container(c, &expected_pair[0], 1)){ + std::cout << "Error after c.emplace();\n"; + return false; + } + c.emplace(1); + if(!test_expected_container(c, &expected_pair[0], 2)){ + std::cout << "Error after c.emplace(1);\n"; + return false; + } + c.emplace(2, 2); + if(!test_expected_container(c, &expected_pair[0], 3)){ + std::cout << "Error after c.emplace(2, 2);\n"; + return false; + } + c.emplace(3, 2, 3); + if(!test_expected_container(c, &expected_pair[0], 4)){ + std::cout << "Error after c.emplace(3, 2, 3);\n"; + return false; + } + c.emplace(4, 2, 3, 4); + if(!test_expected_container(c, &expected_pair[0], 5)){ + std::cout << "Error after c.emplace(4, 2, 3, 4);\n"; + return false; + } + c.emplace(5, 2, 3, 4, 5); + if(!test_expected_container(c, &expected_pair[0], 6)){ + std::cout << "Error after c.emplace(5, 2, 3, 4, 5);\n"; + return false; + } + } + return true; +} + +template +bool test_emplace_assoc_pair(containers_detail::false_) +{ return true; } + +template +bool test_emplace_hint_pair(containers_detail::true_) +{ + std::cout << "Starting test_emplace_hint_pair." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected_pair[0].first) EmplaceInt(); + new(&expected_pair[0].second) EmplaceInt(); + new(&expected_pair[1].first) EmplaceInt(1); + new(&expected_pair[1].second) EmplaceInt(); + new(&expected_pair[2].first) EmplaceInt(2); + new(&expected_pair[2].second) EmplaceInt(2); + new(&expected_pair[3].first) EmplaceInt(3); + new(&expected_pair[3].second) EmplaceInt(2, 3); + new(&expected_pair[4].first) EmplaceInt(4); + new(&expected_pair[4].second) EmplaceInt(2, 3, 4); + new(&expected_pair[5].first) EmplaceInt(5); + new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5); + { + Container c; + typename Container::const_iterator it; + it = c.emplace_hint(c.begin()); + if(!test_expected_container(c, &expected_pair[0], 1)){ + std::cout << "Error after c.emplace(1);\n"; + return false; + } + it = c.emplace_hint(it, 1); + if(!test_expected_container(c, &expected_pair[0], 2)){ + std::cout << "Error after c.emplace(it, 1);\n"; + return false; + } + it = c.emplace_hint(it, 2, 2); + if(!test_expected_container(c, &expected_pair[0], 3)){ + std::cout << "Error after c.emplace(it, 2, 2);\n"; + return false; + } + it = c.emplace_hint(it, 3, 2, 3); + if(!test_expected_container(c, &expected_pair[0], 4)){ + std::cout << "Error after c.emplace(it, 3, 2, 3);\n"; + return false; + } + it = c.emplace_hint(it, 4, 2, 3, 4); + if(!test_expected_container(c, &expected_pair[0], 5)){ + std::cout << "Error after c.emplace(it, 4, 2, 3, 4);\n"; + return false; + } + it = c.emplace_hint(it, 5, 2, 3, 4, 5); + if(!test_expected_container(c, &expected_pair[0], 6)){ + std::cout << "Error after c.emplace(it, 5, 2, 3, 4, 5);\n"; + return false; + } + } + return true; +} + +template +bool test_emplace_hint_pair(containers_detail::false_) +{ return true; } + +template +struct emplace_active +{ + static const bool value = (0 != (O & Mask)); + typedef containers_detail::bool_ type; + operator type() const{ return type(); } +}; + +template +bool test_emplace() +{ +// if(!test_emplace_back(emplace_active())) +// return false; + if(!test_emplace_front(emplace_active())) + return false;/* + if(!test_emplace_before(emplace_active())) + return false; + if(!test_emplace_after(emplace_active())) + return false; + if(!test_emplace_assoc(emplace_active())) + return false; + if(!test_emplace_hint(emplace_active())) + return false; + if(!test_emplace_assoc_pair(emplace_active())) + return false; + if(!test_emplace_hint_pair(emplace_active())) + return false;*/ + return true; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP diff --git a/test/expand_bwd_test_allocator.hpp b/test/expand_bwd_test_allocator.hpp new file mode 100644 index 0000000..1b690e3 --- /dev/null +++ b/test/expand_bwd_test_allocator.hpp @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP +#define BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an allocator to test expand capabilities + +namespace boost { +namespace container { +namespace test { + +//This allocator just allows two allocations. The first one will return +//mp_buffer + m_offset configured in the constructor. The second one +//will return mp_buffer. +template +class expand_bwd_test_allocator +{ + private: + typedef expand_bwd_test_allocator self_t; + typedef void * aux_pointer_t; + typedef const void * cvoid_ptr; + + template + expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&); + + expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&); + + public: + typedef T value_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef typename containers_detail::add_reference + ::type reference; + typedef typename containers_detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef boost::container::containers_detail::version_type version; + + template + struct rebind + { typedef expand_bwd_test_allocator other; }; + + //!Constructor from the segment manager. Never throws + expand_bwd_test_allocator(T *buffer, size_type size, difference_type offset) + : mp_buffer(buffer), m_size(size) + , m_offset(offset), m_allocations(0){ } + + //!Constructor from other expand_bwd_test_allocator. Never throws + expand_bwd_test_allocator(const expand_bwd_test_allocator &other) + : mp_buffer(other.mp_buffer), m_size(other.m_size) + , m_offset(other.m_offset), m_allocations(0){ } + + //!Constructor from related expand_bwd_test_allocator. Never throws + template + expand_bwd_test_allocator(const expand_bwd_test_allocator &other) + : mp_buffer(other.mp_buffer), m_size(other.m_size) + , m_offset(other.m_offset), m_allocations(0){ } + + pointer address(reference value) + { return pointer(addressof(value)); } + + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } + + pointer allocate(size_type , cvoid_ptr hint = 0) + { (void)hint; return 0; } + + void deallocate(const pointer &, size_type) + {} + + template + void construct(pointer ptr, const Convertible &value) + { new((void*)ptr) value_type(value); } + + void destroy(pointer ptr) + { (*ptr).~value_type(); } + + size_type max_size() const + { return m_size; } + + friend void swap(self_t &alloc1, self_t &alloc2) + { + containers_detail::do_swap(alloc1.mp_buffer, alloc2.mp_buffer); + containers_detail::do_swap(alloc1.m_size, alloc2.m_size); + containers_detail::do_swap(alloc1.m_offset, alloc2.m_offset); + } + + //Experimental version 2 expand_bwd_test_allocator functions + + std::pair + allocation_command(boost::container::allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0) + { + (void)preferred_size; (void)reuse; (void)command; + //This allocator only expands backwards! + assert(m_allocations == 0 || (command & boost::container::expand_bwd)); + + received_size = limit_size; + + if(m_allocations == 0){ + if((m_offset + limit_size) > m_size){ + assert(0); + } + ++m_allocations; + return std::pair(mp_buffer + m_offset, false); + } + else if(m_allocations == 1){ + if(limit_size > m_size){ + assert(0); + } + ++m_allocations; + return std::pair(mp_buffer, true); + } + else{ + assert(0); + throw std::bad_alloc(); + } + } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. + size_type size(const pointer &p) const + { (void)p; return m_size; } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::container::bad_alloc if there is no enough memory + pointer allocate_one() + { return this->allocate(1); } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p) + { return this->deallocate(p, 1); } + + pointer mp_buffer; + size_type m_size; + difference_type m_offset; + char m_allocations; +}; + +//!Equality test for same type of expand_bwd_test_allocator +template inline +bool operator==(const expand_bwd_test_allocator &alloc1, + const expand_bwd_test_allocator &alloc2) +{ return false; } + +//!Inequality test for same type of expand_bwd_test_allocator +template inline +bool operator!=(const expand_bwd_test_allocator &alloc1, + const expand_bwd_test_allocator &alloc2) +{ return true; } + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP + diff --git a/test/expand_bwd_test_template.hpp b/test/expand_bwd_test_template.hpp new file mode 100644 index 0000000..7dadcf9 --- /dev/null +++ b/test/expand_bwd_test_template.hpp @@ -0,0 +1,269 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER +#define BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER + +#include +#include +#include +#include "expand_bwd_test_allocator.hpp" +#include +#include + +namespace boost { namespace container { namespace test { + +template +struct value_holder +{ + value_holder(T val) : m_value(val){} + value_holder(): m_value(0){} + ~value_holder(){ m_value = 0; } + bool operator == (const value_holder &other) const + { return m_value == other.m_value; } + bool operator != (const value_holder &other) const + { return m_value != other.m_value; } + + T m_value; +}; + +template +struct triple_value_holder +{ + triple_value_holder(T val) + : m_value1(val) + , m_value2(val) + , m_value3(val) + {} + + triple_value_holder() + : m_value1(0) + , m_value2(0) + , m_value3(0) + {} + + ~triple_value_holder() + { m_value1 = m_value2 = m_value3 = 0; } + + bool operator == (const triple_value_holder &other) const + { + return m_value1 == other.m_value1 + && m_value2 == other.m_value2 + && m_value3 == other.m_value3; + } + + bool operator != (const triple_value_holder &other) const + { + return m_value1 != other.m_value1 + || m_value2 != other.m_value2 + || m_value3 != other.m_value3; + } + + T m_value1; + T m_value2; + T m_value3; +}; + +typedef value_holder int_holder; +typedef triple_value_holder triple_int_holder; + + + +//Function to check if both sets are equal +template +bool CheckEqualVector(const Vector1 &vector1, const Vector2 &vector2) +{ + if(vector1.size() != vector2.size()) + return false; + return std::equal(vector1.begin(), vector1.end(), vector2.begin()); +} + +template +bool CheckUninitializedIsZero(const Vector & v) +{ + typedef typename Vector::value_type value_type; + typename Vector::size_type sz = v.size(); + typename Vector::size_type extra = v.capacity() - v.size(); + value_type comp(0); + + const value_type *holder = &v[0] + sz; + + while(extra--){ + if(*holder++ != comp) + return false; + } + return true; +} + + +//This function tests all the possible combinations when +//inserting data in a vector and expanding backwards +template +bool test_insert_with_expand_bwd() +{ + typedef typename VectorWithExpandBwdAllocator::value_type value_type; + typedef typename boost::remove_volatile::type non_volatile_value_type; + typedef std::vector Vect; + const int MemorySize = 1000; + + //Distance old and new buffer + const int Offset[] = + { 350, 250, 150, 150, + 150, 50, 50, 50 }; + //Insert position + const int Position[] = + { 100, 100, 100, 100, + 100, 100, 100, 100 }; + //Initial vector size + const int InitialSize[] = + { 200, 200, 200, 200, + 200, 200, 200, 200 }; + //Size of the data to insert + const int InsertSize[] = + { 100, 100, 100, 200, + 300, 25, 100, 200 }; + //Number of tests + const int Iterations = sizeof(InsertSize)/sizeof(int); + + for(int iteration = 0; iteration < Iterations; ++iteration) + { + value_type *memory = new value_type[MemorySize]; + try { + std::vector initial_data; + initial_data.resize(InitialSize[iteration]); + for(int i = 0; i < InitialSize[iteration]; ++i){ + initial_data[i] = i; + } + + Vect data_to_insert; + data_to_insert.resize(InsertSize[iteration]); + for(int i = 0; i < InsertSize[iteration]; ++i){ + data_to_insert[i] = -i; + } + + expand_bwd_test_allocator alloc + (&memory[0], MemorySize, Offset[iteration]); + VectorWithExpandBwdAllocator vector(alloc); + vector.insert( vector.begin() + , initial_data.begin(), initial_data.end()); + vector.insert( vector.begin() + Position[iteration] + , data_to_insert.begin(), data_to_insert.end()); + initial_data.insert(initial_data.begin() + Position[iteration] + , data_to_insert.begin(), data_to_insert.end()); + //Now check that values are equal + if(!CheckEqualVector(vector, initial_data)){ + std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl + << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl + << " Iteration: " << iteration << std::endl; + return false; + } + } + catch(...){ + delete [](const_cast(memory)); + throw; + } + delete [](const_cast(memory)); + } + + return true; +} + +//This function tests all the possible combinations when +//inserting data in a vector and expanding backwards +template +bool test_assign_with_expand_bwd() +{ + typedef typename VectorWithExpandBwdAllocator::value_type value_type; + typedef typename boost::remove_volatile::type non_volatile_value_type; + typedef std::vector Vect; + const int MemorySize = 200; + + const int Offset[] = { 50, 50, 50}; + const int InitialSize[] = { 25, 25, 25}; + const int AssignSize[] = { 40, 60, 80}; + const int Iterations = sizeof(AssignSize)/sizeof(int); + + for(int iteration = 0; iteration initial_data; + initial_data.resize(InitialSize[iteration]); + for(int i = 0; i < InitialSize[iteration]; ++i){ + initial_data[i] = i; + } + + //Create data to assign + std::vector data_to_assign; + data_to_assign.resize(AssignSize[iteration]); + for(int i = 0; i < AssignSize[iteration]; ++i){ + data_to_assign[i] = -i; + } + + //Insert initial data to the vector to test + expand_bwd_test_allocator alloc + (&memory[0], MemorySize, Offset[iteration]); + VectorWithExpandBwdAllocator vector(alloc); + vector.insert( vector.begin() + , initial_data.begin(), initial_data.end()); + + //Assign data + vector.assign(data_to_assign.begin(), data_to_assign.end()); + initial_data.assign(data_to_assign.begin(), data_to_assign.end()); + + //Now check that values are equal + if(!CheckEqualVector(vector, initial_data)){ + std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl + << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl + << " Iteration: " << iteration << std::endl; + return false; + } + } + catch(...){ + delete [](const_cast::type*>(memory)); + throw; + } + delete [](const_cast::type*>(memory)); + } + + return true; +} + +//This function calls all tests +template +bool test_all_expand_bwd() +{ + std::cout << "Starting test_insert_with_expand_bwd." << std::endl << " Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + + if(!test_insert_with_expand_bwd()){ + std::cout << "test_allocation_direct_deallocation failed. Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + return false; + } + + std::cout << "Starting test_assign_with_expand_bwd." << std::endl << " Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + + if(!test_assign_with_expand_bwd()){ + std::cout << "test_allocation_direct_deallocation failed. Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + return false; + } + + return true; +} + +}}} //namespace boost { namespace container { namespace test { + +#include + +#endif //BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp new file mode 100644 index 0000000..e8f9173 --- /dev/null +++ b/test/flat_tree_test.cpp @@ -0,0 +1,333 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "print_container.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "set_test.hpp" +#include "map_test.hpp" +#include "emplace_test.hpp" + +using namespace boost::container; + +//Alias allocator type +typedef std::allocator allocator_t; +typedef std::allocator + movable_allocator_t; +typedef std::allocator > + pair_allocator_t; +typedef std::allocator > + movable_pair_allocator_t; +typedef std::allocator + move_copy_allocator_t; +typedef std::allocator > + move_copy_pair_allocator_t; +typedef std::allocator + copy_allocator_t; +typedef std::allocator > + copy_pair_allocator_t; + + +//Alias set types +typedef std::set MyStdSet; +typedef std::multiset MyStdMultiSet; +typedef std::map MyStdMap; +typedef std::multimap MyStdMultiMap; + +typedef flat_set, allocator_t> MyBoostSet; +typedef flat_multiset, allocator_t> MyBoostMultiSet; +typedef flat_map, pair_allocator_t> MyBoostMap; +typedef flat_multimap, pair_allocator_t> MyBoostMultiMap; + +typedef flat_set + ,movable_allocator_t> MyMovableBoostSet; +typedef flat_multiset + ,movable_allocator_t> MyMovableBoostMultiSet; +typedef flat_map + ,movable_pair_allocator_t> MyMovableBoostMap; +typedef flat_multimap + ,movable_pair_allocator_t> MyMovableBoostMultiMap; + +typedef flat_set + ,move_copy_allocator_t> MyMoveCopyBoostSet; +typedef flat_multiset + ,move_copy_allocator_t> MyMoveCopyBoostMultiSet; +typedef flat_map + ,move_copy_pair_allocator_t> MyMoveCopyBoostMap; +typedef flat_multimap + ,move_copy_pair_allocator_t> MyMoveCopyBoostMultiMap; + +typedef flat_set + ,copy_allocator_t> MyCopyBoostSet; +typedef flat_multiset + ,copy_allocator_t> MyCopyBoostMultiSet; +typedef flat_map + ,copy_pair_allocator_t> MyCopyBoostMap; +typedef flat_multimap + ,copy_pair_allocator_t> MyCopyBoostMultiMap; + + + +//Test recursive structures +class recursive_flat_set +{ + public: + recursive_flat_set(const recursive_flat_set &c) + : id_(c.id_), flat_set_(c.flat_set_) + {} + + recursive_flat_set & operator =(const recursive_flat_set &c) + { + id_ = c.id_; + flat_set_= c.flat_set_; + return *this; + } + int id_; + flat_set flat_set_; + friend bool operator< (const recursive_flat_set &a, const recursive_flat_set &b) + { return a.id_ < b.id_; } +}; + + + +class recursive_flat_map +{ + public: + recursive_flat_map(const recursive_flat_map &c) + : id_(c.id_), map_(c.map_) + {} + + recursive_flat_map & operator =(const recursive_flat_map &c) + { + id_ = c.id_; + map_= c.map_; + return *this; + } + + int id_; + flat_map map_; + + friend bool operator< (const recursive_flat_map &a, const recursive_flat_map &b) + { return a.id_ < b.id_; } +}; + +//Test recursive structures +class recursive_flat_multiset +{ + public: + recursive_flat_multiset(const recursive_flat_multiset &c) + : id_(c.id_), flat_set_(c.flat_set_) + {} + + recursive_flat_multiset & operator =(const recursive_flat_multiset &c) + { + id_ = c.id_; + flat_set_= c.flat_set_; + return *this; + } + int id_; + flat_multiset flat_set_; + friend bool operator< (const recursive_flat_multiset &a, const recursive_flat_multiset &b) + { return a.id_ < b.id_; } +}; + +class recursive_flat_multimap +{ +public: + recursive_flat_multimap(const recursive_flat_multimap &c) + : id_(c.id_), map_(c.map_) + {} + + recursive_flat_multimap & operator =(const recursive_flat_multimap &c) + { + id_ = c.id_; + map_= c.map_; + return *this; + } + int id_; + flat_map map_; + friend bool operator< (const recursive_flat_multimap &a, const recursive_flat_multimap &b) + { return a.id_ < b.id_; } +}; + +template +void test_move() +{ + //Now test move semantics + C original; + C move_ctor(boost::move(original)); + C move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); +} + +int main() +{ + using namespace boost::container::test; + + //Now test move semantics + { + test_move >(); + test_move >(); + test_move >(); + test_move >(); + } + + + if (0 != set_test< + MyBoostSet + ,MyStdSet + ,MyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test_copyable< + MyBoostSet + ,MyStdSet + ,MyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test< + MyMovableBoostSet + ,MyStdSet + ,MyMovableBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test< + MyMoveCopyBoostSet + ,MyStdSet + ,MyMoveCopyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test_copyable< + MyMoveCopyBoostSet + ,MyStdSet + ,MyMoveCopyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test< + MyCopyBoostSet + ,MyStdSet + ,MyCopyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test_copyable< + MyCopyBoostSet + ,MyStdSet + ,MyCopyBoostMultiSet + ,MyStdMultiSet>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test< + MyBoostMap + ,MyStdMap + ,MyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test_copyable< + MyBoostMap + ,MyStdMap + ,MyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + +// if (0 != map_test< +// MyMovableBoostMap +// ,MyStdMap +// ,MyMovableBoostMultiMap +// ,MyStdMultiMap>()){ +// return 1; +// } + + if (0 != map_test< + MyMoveCopyBoostMap + ,MyStdMap + ,MyMoveCopyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test_copyable< + MyMoveCopyBoostMap + ,MyStdMap + ,MyMoveCopyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test< + MyCopyBoostMap + ,MyStdMap + ,MyCopyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test_copyable< + MyCopyBoostMap + ,MyStdMap + ,MyCopyBoostMultiMap + ,MyStdMultiMap>()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC); + const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR); + +// if(!boost::container::test::test_emplace, MapOptions>()) +// return 1; + if(!boost::container::test::test_emplace, MapOptions>()) + return 1; + if(!boost::container::test::test_emplace, SetOptions>()) + return 1; + if(!boost::container::test::test_emplace, SetOptions>()) + return 1; + return 0; +} + +#include diff --git a/test/heap_allocator_v1.hpp b/test/heap_allocator_v1.hpp new file mode 100644 index 0000000..1e572c3 --- /dev/null +++ b/test/heap_allocator_v1.hpp @@ -0,0 +1,159 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP +#define BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an heap_allocator_v1 that allocates portions of fixed size +//!memory buffer (shared memory, mapped file...) + +namespace boost { +namespace container { +namespace test { + +//!An STL compatible heap_allocator_v1 that uses a segment manager as +//!memory source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the heap_allocator_v1 in shared memory, memory mapped-files, etc...*/ +template +class heap_allocator_v1 +{ + private: + typedef heap_allocator_v1 self_t; + typedef SegmentManager segment_manager; + typedef typename segment_manager::void_pointer aux_pointer_t; + + typedef typename + boost::pointer_to_other + ::type cvoid_ptr; + + typedef typename boost::pointer_to_other + ::type alloc_ptr_t; + + template + heap_allocator_v1& operator=(const heap_allocator_v1&); + + heap_allocator_v1& operator=(const heap_allocator_v1&); + + alloc_ptr_t mp_mngr; + + public: + typedef T value_type; + typedef typename boost::pointer_to_other + ::type pointer; + typedef typename boost:: + pointer_to_other::type const_pointer; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + //!Obtains an heap_allocator_v1 of other type + template + struct rebind + { + typedef heap_allocator_v1 other; + }; + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager()const + { return detail::get_pointer(mp_mngr); } +/* + //!Returns address of mutable object. Never throws + pointer address(reference value) const + { return pointer(addressof(value)); } + + //!Returns address of non mutable object. Never throws + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } +*/ + //!Constructor from the segment manager. Never throws + heap_allocator_v1(segment_manager *segment_mngr) + : mp_mngr(segment_mngr) { } + + //!Constructor from other heap_allocator_v1. Never throws + heap_allocator_v1(const heap_allocator_v1 &other) + : mp_mngr(other.get_segment_manager()){ } + + //!Constructor from related heap_allocator_v1. Never throws + template + heap_allocator_v1(const heap_allocator_v1 &other) + : mp_mngr(other.get_segment_manager()){} + + //!Allocates memory for an array of count elements. + //!Throws boost::container::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_ptr hint = 0) + { (void)hint; return ::new value_type[count]; } + + //!Deallocates memory previously allocated. Never throws + void deallocate(const pointer &ptr, size_type) + { return ::delete[] detail::get_pointer(ptr) ; } + + //!Construct object, calling constructor. + //!Throws if T(const T&) throws + void construct(const pointer &ptr, const_reference value) + { new((void*)detail::get_pointer(ptr)) value_type(value); } + + //!Destroys object. Throws if object's destructor throws + void destroy(const pointer &ptr) + { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); } + + //!Returns the number of elements that could be allocated. Never throws + size_type max_size() const + { return mp_mngr->get_size(); } + + //!Swap segment manager. Does not throw. If each heap_allocator_v1 is placed in + //!different memory segments, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { detail::do_swap(alloc1.mp_mngr, alloc2.mp_mngr); } +}; + +//!Equality test for same type of heap_allocator_v1 +template inline +bool operator==(const heap_allocator_v1 &alloc1, + const heap_allocator_v1 &alloc2) + { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); } + +//!Inequality test for same type of heap_allocator_v1 +template inline +bool operator!=(const heap_allocator_v1 &alloc1, + const heap_allocator_v1 &alloc2) + { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); } + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP + diff --git a/test/list_test.cpp b/test/list_test.cpp new file mode 100644 index 0000000..9127ee1 --- /dev/null +++ b/test/list_test.cpp @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" +#include "emplace_test.hpp" + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +template class boost::container::list >; +typedef list MyList; + +typedef list MyMoveList; +typedef list MyCopyMoveList; +typedef list MyCopyList; + +class recursive_list +{ +public: + int id_; + list list_; + recursive_list &operator=(const recursive_list &o) + { list_ = o.list_; return *this; } +}; + +void recursive_list_test()//Test for recursive types +{ + list recursive, copy; + //Test to test both move emulations + if(!copy.size()){ + copy = recursive; + } +} + +int main () +{ + recursive_list_test(); + { + //Now test move semantics + list original; + list move_ctor(boost::move(original)); + list move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); + + if(!boost::container::test::test_emplace, Options>()) + return 1; + + return 0; +} + +#include diff --git a/test/list_test.hpp b/test/list_test.hpp new file mode 100644 index 0000000..121c287 --- /dev/null +++ b/test/list_test.hpp @@ -0,0 +1,312 @@ +//////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +//////////////////////////////////////// + +#ifndef BOOST_CONTAINER_TEST_LIST_TEST_HEADER +#define BOOST_CONTAINER_TEST_LIST_TEST_HEADER + +#include +#include "check_equal_containers.hpp" +#include +#include +#include +#include +#include "print_container.hpp" +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +template +bool list_copyable_only(V1 *, V2 *, boost::container::containers_detail::false_type) +{ + return true; +} + +//Function to check if both sets are equal +template +bool list_copyable_only(V1 *boostlist, V2 *stdlist, boost::container::containers_detail::true_type) +{ + typedef typename V1::value_type IntType; + boostlist->insert(boostlist->end(), 50, IntType(1)); + stdlist->insert(stdlist->end(), 50, 1); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + + { + IntType move_me(1); + boostlist->insert(boostlist->begin(), 50, boost::move(move_me)); + stdlist->insert(stdlist->begin(), 50, 1); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + } + { + IntType move_me(2); + boostlist->assign(boostlist->size()/2, boost::move(move_me)); + stdlist->assign(stdlist->size()/2, 2); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + } + { + IntType move_me(3); + boostlist->assign(boostlist->size()*3-1, boost::move(move_me)); + stdlist->assign(stdlist->size()*3-1, 3); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + } + + { + IntType copy_me(3); + const IntType ccopy_me(3); + boostlist->push_front(copy_me); + stdlist->push_front(int(3)); + boostlist->push_front(ccopy_me); + stdlist->push_front(int(3)); + if(!test::CheckEqualContainers(boostlist, stdlist)) return false; + } + + return true; +} + +template +struct list_push_data_function +{ + template + static int execute(int max, MyBoostList *boostlist, MyStdList *stdlist) + { + typedef typename MyBoostList::value_type IntType; + for(int i = 0; i < max; ++i){ + IntType move_me(i); + boostlist->push_back(boost::move(move_me)); + stdlist->push_back(i); + boostlist->push_front(IntType(i)); + stdlist->push_front(int(i)); + } + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + return 0; + } +}; + +template<> +struct list_push_data_function +{ + template + static int execute(int max, MyBoostList *boostlist, MyStdList *stdlist) + { + typedef typename MyBoostList::value_type IntType; + for(int i = 0; i < max; ++i){ + IntType move_me(i); + boostlist->push_front(boost::move(move_me)); + stdlist->push_front(i); + boostlist->push_front(IntType(i)); + stdlist->push_front(int(i)); + } + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + return 0; + } +}; + +template +struct list_pop_back_function +{ + template + static int execute(MyBoostList *boostlist, MyStdList *stdlist) + { + boostlist->pop_back(); + stdlist->pop_back(); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + return 0; + } +}; + +template<> +struct list_pop_back_function +{ + template + static int execute(MyBoostList *boostlist, MyStdList *stdlist) + { + (void)boostlist; (void)stdlist; + return 0; + } +}; + +template +int list_test (bool copied_allocators_equal = true) +{ + typedef std::list MyStdList; + typedef typename MyBoostList::value_type IntType; + const int max = 100; + typedef list_push_data_function push_data_t; + + try{ + MyBoostList *boostlist = new MyBoostList; + MyStdList *stdlist = new MyStdList; + + if(push_data_t::execute(max, boostlist, stdlist)){ + return 1; + } + + boostlist->erase(boostlist->begin()++); + stdlist->erase(stdlist->begin()++); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + + if(list_pop_back_function::execute(boostlist, stdlist)){ + return 1; + } + + boostlist->pop_front(); + stdlist->pop_front(); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + boostlist->assign(boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(&aux_vect[50])); + stdlist->assign(&aux_vect2[0], &aux_vect2[50]); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + } + + if(copied_allocators_equal){ + boostlist->sort(); + stdlist->sort(); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + } + + boostlist->reverse(); + stdlist->reverse(); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + + boostlist->reverse(); + stdlist->reverse(); + if(!CheckEqualContainers(boostlist, stdlist)) return 1; + + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + boostlist->insert(boostlist->begin() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(&aux_vect[50])); + stdlist->insert(stdlist->begin(), &aux_vect2[0], &aux_vect2[50]); + } + + boostlist->unique(); + stdlist->unique(); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + + if(copied_allocators_equal){ + boostlist->sort(std::greater()); + stdlist->sort(std::greater()); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + } + + for(int i = 0; i < max; ++i){ + IntType new_int(i); + boostlist->insert(boostlist->end(), boost::move(new_int)); + stdlist->insert(stdlist->end(), i); + if(!test::CheckEqualContainers(boostlist, stdlist)) return 1; + } + if(!test::CheckEqualContainers(boostlist, stdlist)) return 1; + + boostlist->resize(25); + stdlist->resize(25); + boostlist->resize(50); + stdlist->resize(50); + boostlist->resize(0); + stdlist->resize(0); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + + if(push_data_t::execute(max, boostlist, stdlist)){ + return 1; + } + { + MyBoostList otherboostlist(boostlist->get_allocator()); + MyStdList otherstdlist; + + int listsize = (int)boostlist->size(); + + if(push_data_t::execute(listsize, boostlist, stdlist)){ + return 1; + } + + if(copied_allocators_equal){ + boostlist->splice(boostlist->begin(), otherboostlist); + stdlist->splice(stdlist->begin(), otherstdlist); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + } + + listsize = (int)boostlist->size(); + + if(push_data_t::execute(listsize, boostlist, stdlist)){ + return 1; + } + + if(push_data_t::execute(listsize, &otherboostlist, &otherstdlist)){ + return 1; + } + + if(copied_allocators_equal){ + boostlist->sort(std::greater()); + stdlist->sort(std::greater()); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + + otherboostlist.sort(std::greater()); + otherstdlist.sort(std::greater()); + if(!CheckEqualContainers(&otherboostlist, &otherstdlist)) + return 1; + + boostlist->merge(otherboostlist, std::greater()); + stdlist->merge(otherstdlist, std::greater()); + if(!CheckEqualContainers(boostlist, stdlist)) + return 1; + } + + if(!list_copyable_only(boostlist, stdlist + ,containers_detail::bool_::value>())){ + return 1; + } + } + + delete boostlist; + delete stdlist; + } + catch(...){ + throw; + } + return 0; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif diff --git a/test/map_test.hpp b/test/map_test.hpp new file mode 100644 index 0000000..f41acba --- /dev/null +++ b/test/map_test.hpp @@ -0,0 +1,521 @@ +//////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +//////////////////////////////////////// + +#ifndef BOOST_CONTAINER_TEST_MAP_TEST_HEADER +#define BOOST_CONTAINER_TEST_MAP_TEST_HEADER + +#include +#include "check_equal_containers.hpp" +#include +#include +#include +#include "print_container.hpp" +#include +#include +#include + +template +bool operator ==(std::pair &p1, std::pair &p2) +{ + return p1.first == p2.first && p1.second == p2.second; +} + +namespace boost{ +namespace container { +namespace test{ + +template +int map_test () +{ + typedef typename MyBoostMap::key_type IntType; + typedef containers_detail::pair IntPairType; + typedef typename MyStdMap::value_type StdPairType; + const int max = 100; + + try{ + MyBoostMap *boostmap = new MyBoostMap; + MyStdMap *stdmap = new MyStdMap; + MyBoostMultiMap *boostmultimap = new MyBoostMultiMap; + MyStdMultiMap *stdmultimap = new MyStdMultiMap; + + //Test construction from a range + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + typedef typename MyStdMap::value_type StdValueType; + typedef typename MyStdMap::key_type StdKeyType; + typedef typename MyStdMap::mapped_type StdMappedType; + StdValueType aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + MyBoostMap *boostmap2 = new MyBoostMap + ( boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(aux_vect + 50)); + MyStdMap *stdmap2 = new MyStdMap(aux_vect2, aux_vect2 + 50); + MyBoostMultiMap *boostmultimap2 = new MyBoostMultiMap + ( boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(aux_vect3 + 50)); + MyStdMultiMap *stdmultimap2 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(boostmap2, stdmap2)) return 1; + if(!CheckEqualContainers(boostmultimap2, stdmultimap2)) return 1; + + //ordered range insertion + //This is really nasty, but we have no other simple choice + for(int i = 0; i < 50; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i), StdMappedType(i)); + } + + for(int i = 0; i < 50; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } +/* + MyBoostMap *boostmap3 = new MyBoostMap + ( ordered_unique_range + , boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(aux_vect + 50)); + MyStdMap *stdmap3 = new MyStdMap(aux_vect2, aux_vect2 + 50); + MyBoostMultiMap *boostmultimap3 = new MyBoostMultiMap + ( ordered_range + , boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(aux_vect3 + 50)); + MyStdMultiMap *stdmultimap3 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50); + + if(!CheckEqualContainers(boostmap3, stdmap3)){ + std::cout << "Error in construct(MyBoostMap3)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultimap3, stdmultimap3)){ + std::cout << "Error in construct(MyBoostMultiMap3)" << std::endl; + return 1; + } +*/ + delete boostmap2; + delete boostmultimap2; + delete stdmap2; + delete stdmultimap2; + //delete boostmap3; + //delete boostmultimap3; + //delete stdmap3; + //delete stdmultimap3; + } + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < max; ++i){ + boostmap->insert(boost::move(aux_vect[i])); + stdmap->insert(StdPairType(i, i)); + boostmultimap->insert(boost::move(aux_vect3[i])); + stdmultimap->insert(StdPairType(i, i)); + } + + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + typename MyBoostMap::iterator it; + typename MyBoostMap::const_iterator cit = it; + + boostmap->erase(boostmap->begin()++); + stdmap->erase(stdmap->begin()++); + boostmultimap->erase(boostmultimap->begin()++); + stdmultimap->erase(stdmultimap->begin()++); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + boostmap->erase(boostmap->begin()); + stdmap->erase(stdmap->begin()); + boostmultimap->erase(boostmultimap->begin()); + stdmultimap->erase(stdmultimap->begin()); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + //Swapping test + MyBoostMap tmpboostemap2; + MyStdMap tmpstdmap2; + MyBoostMultiMap tmpboostemultimap2; + MyStdMultiMap tmpstdmultimap2; + boostmap->swap(tmpboostemap2); + stdmap->swap(tmpstdmap2); + boostmultimap->swap(tmpboostemultimap2); + stdmultimap->swap(tmpstdmultimap2); + boostmap->swap(tmpboostemap2); + stdmap->swap(tmpstdmap2); + boostmultimap->swap(tmpboostemultimap2); + stdmultimap->swap(tmpstdmultimap2); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + //Insertion from other container + //Initialize values + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + boostmap->insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(aux_vect + 50)); + boostmultimap->insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50)); + for(std::size_t i = 0; i != 50; ++i){ + StdPairType stdpairtype(-1, -1); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + } + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + for(int i = 0, j = static_cast(boostmap->size()); i < j; ++i){ + boostmap->erase(IntType(i)); + stdmap->erase(i); + boostmultimap->erase(IntType(i)); + stdmultimap->erase(i); + } + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + { + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect4[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect4[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect5[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect5[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + boostmap->insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(aux_vect + 50)); + boostmap->insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50)); + boostmultimap->insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(aux_vect4 + 50)); + boostmultimap->insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(aux_vect5 + 50)); + + for(std::size_t i = 0; i != 50; ++i){ + StdPairType stdpairtype(-1, -1); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + } + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + boostmap->erase(boostmap->begin()->first); + stdmap->erase(stdmap->begin()->first); + boostmultimap->erase(boostmultimap->begin()->first); + stdmultimap->erase(stdmultimap->begin()->first); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < max; ++i){ + boostmap->insert(boost::move(aux_vect[i])); + stdmap->insert(StdPairType(i, i)); + boostmultimap->insert(boost::move(aux_vect3[i])); + stdmultimap->insert(StdPairType(i, i)); + } + + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + + for(int i = 0; i < max; ++i){ + IntPairType intpair; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmap->insert(boostmap->begin(), boost::move(intpair)); + stdmap->insert(stdmap->begin(), StdPairType(i, i)); + //PrintContainers(boostmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmultimap->insert(boostmultimap->begin(), boost::move(intpair)); + stdmultimap->insert(stdmultimap->begin(), StdPairType(i, i)); + //PrintContainers(boostmultimap, stdmultimap); + if(!CheckEqualPairContainers(boostmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmap->insert(boostmap->end(), boost::move(intpair)); + stdmap->insert(stdmap->end(), StdPairType(i, i)); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmultimap->insert(boostmultimap->end(), boost::move(intpair)); + stdmultimap->insert(stdmultimap->end(), StdPairType(i, i)); + if(!CheckEqualPairContainers(boostmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmap->insert(boostmap->lower_bound(IntType(i)), boost::move(intpair)); + stdmap->insert(stdmap->lower_bound(i), StdPairType(i, i)); + //PrintContainers(boostmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + boostmultimap->insert(boostmultimap->lower_bound(boost::move(i1)), boost::move(intpair)); + stdmultimap->insert(stdmultimap->lower_bound(i), StdPairType(i, i)); + } + + //PrintContainers(boostmultimap, stdmultimap); + if(!CheckEqualPairContainers(boostmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + boostmap->insert(boostmap->upper_bound(boost::move(i1)), boost::move(intpair)); + stdmap->insert(stdmap->upper_bound(i), StdPairType(i, i)); + } + //PrintContainers(boostmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + boostmultimap->insert(boostmultimap->upper_bound(boost::move(i1)), boost::move(intpair)); + stdmultimap->insert(stdmultimap->upper_bound(i), StdPairType(i, i)); + } + //PrintContainers(boostmultimap, stdmultimap); + if(!CheckEqualPairContainers(boostmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) + return 1; + } + + //Compare count with std containers + for(int i = 0; i < max; ++i){ + if(boostmap->count(IntType(i)) != stdmap->count(i)){ + return -1; + } + + if(boostmultimap->count(IntType(i)) != stdmultimap->count(i)){ + return -1; + } + } + + //Now do count exercise + boostmap->erase(boostmap->begin(), boostmap->end()); + boostmultimap->erase(boostmultimap->begin(), boostmultimap->end()); + boostmap->clear(); + boostmultimap->clear(); + + for(int j = 0; j < 3; ++j) + for(int i = 0; i < 100; ++i){ + IntPairType intpair; + { + IntType i1(i), i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmap->insert(boost::move(intpair)); + { + IntType i1(i), i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + boostmultimap->insert(boost::move(intpair)); + if(boostmap->count(IntType(i)) != typename MyBoostMultiMap::size_type(1)) + return 1; + if(boostmultimap->count(IntType(i)) != typename MyBoostMultiMap::size_type(j+1)) + return 1; + } + } + + delete boostmap; + delete stdmap; + delete boostmultimap; + delete stdmultimap; + } + catch(...){ + throw; + } + return 0; +} + +template +int map_test_copyable () +{ + typedef typename MyBoostMap::key_type IntType; + typedef containers_detail::pair IntPairType; + typedef typename MyStdMap::value_type StdPairType; + + const int max = 100; + + try{ + MyBoostMap *boostmap = new MyBoostMap; + MyStdMap *stdmap = new MyStdMap; + MyBoostMultiMap *boostmultimap = new MyBoostMultiMap; + MyStdMultiMap *stdmultimap = new MyStdMultiMap; + + int i; + for(i = 0; i < max; ++i){ + { + IntType i1(i), i2(i); + IntPairType intpair1(boost::move(i1), boost::move(i2)); + boostmap->insert(boost::move(intpair1)); + stdmap->insert(StdPairType(i, i)); + } + { + IntType i1(i), i2(i); + IntPairType intpair2(boost::move(i1), boost::move(i2)); + boostmultimap->insert(boost::move(intpair2)); + stdmultimap->insert(StdPairType(i, i)); + } + } + if(!CheckEqualContainers(boostmap, stdmap)) return 1; + if(!CheckEqualContainers(boostmultimap, stdmultimap)) return 1; + + { + //Now, test copy constructor + MyBoostMap boostmapcopy(*boostmap); + MyStdMap stdmapcopy(*stdmap); + MyBoostMultiMap boostmmapcopy(*boostmultimap); + MyStdMultiMap stdmmapcopy(*stdmultimap); + + if(!CheckEqualContainers(&boostmapcopy, &stdmapcopy)) + return 1; + if(!CheckEqualContainers(&boostmmapcopy, &stdmmapcopy)) + return 1; + + //And now assignment + boostmapcopy = *boostmap; + stdmapcopy = *stdmap; + boostmmapcopy = *boostmultimap; + stdmmapcopy = *stdmultimap; + + if(!CheckEqualContainers(&boostmapcopy, &stdmapcopy)) + return 1; + if(!CheckEqualContainers(&boostmmapcopy, &stdmmapcopy)) + return 1; + delete boostmap; + delete boostmultimap; + delete stdmap; + delete stdmultimap; + } + } + catch(...){ + throw; + } + return 0; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_MAP_TEST_HEADER diff --git a/test/movable_int.hpp b/test/movable_int.hpp new file mode 100644 index 0000000..37bf71d --- /dev/null +++ b/test/movable_int.hpp @@ -0,0 +1,230 @@ +/////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER +#define BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER + +#include +#include +#include + +namespace boost { +namespace container { +namespace test { + +template +struct is_copyable; + +template<> +struct is_copyable +{ + static const bool value = true; +}; + + +class movable_int +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_int) + + public: + movable_int() + : m_int(0) + {} + + explicit movable_int(int a) + : m_int(a) + {} + + movable_int(BOOST_RV_REF(movable_int) mmi) + : m_int(mmi.m_int) + { mmi.m_int = 0; } + + movable_int & operator= (BOOST_RV_REF(movable_int) mmi) + { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } + + movable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const movable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const movable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const movable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const movable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const movable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const movable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, movable_int const & p) + +{ + os << p.get_int(); + return os; +} + + +template<> +struct is_copyable +{ + static const bool value = false; +}; + +class movable_and_copyable_int +{ + BOOST_COPYABLE_AND_MOVABLE(movable_and_copyable_int) + + public: + movable_and_copyable_int() + : m_int(0) + {} + + explicit movable_and_copyable_int(int a) + : m_int(a) + {} + + movable_and_copyable_int(const movable_and_copyable_int& mmi) + : m_int(mmi.m_int) + {} + + movable_and_copyable_int(BOOST_RV_REF(movable_and_copyable_int) mmi) + : m_int(mmi.m_int) + { mmi.m_int = 0; } + + movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi) + { this->m_int = mi.m_int; return *this; } + + movable_and_copyable_int & operator= (BOOST_RV_REF(movable_and_copyable_int) mmi) + { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } + + movable_and_copyable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const movable_and_copyable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const movable_and_copyable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const movable_and_copyable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const movable_and_copyable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const movable_and_copyable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const movable_and_copyable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, movable_and_copyable_int const & p) + +{ + os << p.get_int(); + return os; +} + +template<> +struct is_copyable +{ + static const bool value = true; +}; + +class copyable_int +{ + public: + copyable_int() + : m_int(0) + {} + + explicit copyable_int(int a) + : m_int(a) + {} + + copyable_int(const copyable_int& mmi) + : m_int(mmi.m_int) + {} + + copyable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const copyable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const copyable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const copyable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const copyable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const copyable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const copyable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, copyable_int const & p) + +{ + os << p.get_int(); + return os; +} + +template<> +struct is_copyable +{ + static const bool value = true; +}; + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER diff --git a/test/print_container.hpp b/test/print_container.hpp new file mode 100644 index 0000000..9300c3c --- /dev/null +++ b/test/print_container.hpp @@ -0,0 +1,64 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_PRINTCONTAINER_HPP +#define BOOST_PRINTCONTAINER_HPP + +#include +#include +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +struct PrintValues : public std::unary_function +{ + void operator() (int value) const + { + std::cout << value << " "; + } +}; + +template +void PrintContents(const Container &cont, const char *contName) +{ + std::cout<< "Printing contents of " << contName << std::endl; + std::for_each(cont.begin(), cont.end(), PrintValues()); + std::cout<< std::endl << std::endl; +} + +//Function to dump data +template +void PrintContainers(MyBoostCont *boostcont, MyStdCont *stdcont) +{ + typename MyBoostCont::iterator itboost = boostcont->begin(), itboostend = boostcont->end(); + typename MyStdCont::iterator itstd = stdcont->begin(), itstdend = stdcont->end(); + + std::cout << "MyBoostCont" << std::endl; + for(; itboost != itboostend; ++itboost){ + std::cout << *itboost << std::endl; + } + std::cout << "MyStdCont" << std::endl; + + for(; itstd != itstdend; ++itstd){ + std::cout << *itstd << std::endl; + } +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_PRINTCONTAINER_HPP diff --git a/test/set_test.hpp b/test/set_test.hpp new file mode 100644 index 0000000..e4061eb --- /dev/null +++ b/test/set_test.hpp @@ -0,0 +1,504 @@ +//////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +//////////////////////////////////////// + +#ifndef BOOST_CONTAINER_TEST_SET_TEST_HEADER +#define BOOST_CONTAINER_TEST_SET_TEST_HEADER + +#include +#include "check_equal_containers.hpp" +#include +#include +#include +#include "print_container.hpp" +#include +#include + +namespace boost{ +namespace container { +namespace test{ + +template +int set_test () +{ + typedef typename MyBoostSet::value_type IntType; + const int max = 100; + + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyBoostSet *boostset = new MyBoostSet; + MyStdSet *stdset = new MyStdSet; + MyBoostMultiSet *boostmultiset = new MyBoostMultiSet; + MyStdMultiSet *stdmultiset = new MyStdMultiSet; + + //Test construction from a range + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(i/2); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = i/2; + } + IntType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(i/2); + aux_vect3[i] = boost::move(move_me); + } + + MyBoostSet *boostset2 = new MyBoostSet + ( boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(aux_vect + 50)); + MyStdSet *stdset2 = new MyStdSet(aux_vect2, aux_vect2 + 50); + MyBoostMultiSet *boostmultiset2 = new MyBoostMultiSet + ( boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(aux_vect3 + 50)); + MyStdMultiSet *stdmultiset2 = new MyStdMultiSet(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(boostset2, stdset2)){ + std::cout << "Error in construct(MyBoostSet2)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset2, stdmultiset2)){ + std::cout << "Error in construct(MyBoostMultiSet2)" << std::endl; + return 1; + } + + //ordered range insertion + for(int i = 0; i < 50; ++i){ + IntType move_me(i); + aux_vect[i] = boost::move(move_me); + } + + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = i; + } + + for(int i = 0; i < 50; ++i){ + IntType move_me(i); + aux_vect3[i] = boost::move(move_me); + } +/* + MyBoostSet *boostset3 = MyBoostSet + ( ordered_unique_range + , boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(aux_vect + 50)); + MyStdSet *stdset3 = new MyStdSet(aux_vect2, aux_vect2 + 50); + MyBoostMultiSet *boostmultiset3 = MyBoostMultiSet + ( ordered_range + , boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(aux_vect3 + 50)); + MyStdMultiSet *stdmultiset3 = new MyStdMultiSet(aux_vect2, aux_vect2 + 50); + + if(!CheckEqualContainers(boostset3, stdset3)){ + std::cout << "Error in construct(MyBoostSet3)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset3, stdmultiset3)){ + std::cout << "Error in construct(MyBoostMultiSet3)" << std::endl; + return 1; + } +*/ + delete boostset2; + delete boostmultiset2; + delete stdset2; + delete stdmultiset2; + //delete boostset3; + //delete boostmultiset3; + //delete stdset3; + //delete stdmultiset3; + } + + int i, j; + for(i = 0; i < max; ++i){ + IntType move_me(i); + boostset->insert(boost::move(move_me)); + stdset->insert(i); + boostset->insert(IntType(i)); + stdset->insert(i); + IntType move_me2(i); + boostmultiset->insert(boost::move(move_me2)); + stdmultiset->insert(i); + boostmultiset->insert(IntType(i)); + stdmultiset->insert(i); + } + + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boost::move(move_me)" << std::endl; + return 1; + } + + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boost::move(move_me)" << std::endl; + return 1; + } + + typename MyBoostSet::iterator it; + typename MyBoostSet::const_iterator cit = it; + + boostset->erase(boostset->begin()++); + stdset->erase(stdset->begin()++); + boostmultiset->erase(boostmultiset->begin()++); + stdmultiset->erase(stdmultiset->begin()++); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->erase(boostset->begin()++)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->erase(boostmultiset->begin()++)" << std::endl; + return 1; + } + + boostset->erase(boostset->begin()); + stdset->erase(stdset->begin()); + boostmultiset->erase(boostmultiset->begin()); + stdmultiset->erase(stdmultiset->begin()); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->erase(boostset->begin())" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->erase(boostmultiset->begin())" << std::endl; + return 1; + } + + //Swapping test + MyBoostSet tmpboosteset2; + MyStdSet tmpstdset2; + MyBoostMultiSet tmpboostemultiset2; + MyStdMultiSet tmpstdmultiset2; + boostset->swap(tmpboosteset2); + stdset->swap(tmpstdset2); + boostmultiset->swap(tmpboostemultiset2); + stdmultiset->swap(tmpstdmultiset2); + boostset->swap(tmpboosteset2); + stdset->swap(tmpstdset2); + boostmultiset->swap(tmpboostemultiset2); + stdmultiset->swap(tmpstdmultiset2); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->swap(tmpboosteset2)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->swap(tmpboostemultiset2)" << std::endl; + return 1; + } + + //Insertion from other container + //Initialize values + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + IntType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect3[i] = boost::move(move_me); + } + + boostset->insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(aux_vect + 50)); + stdset->insert(aux_vect2, aux_vect2 + 50); + boostmultiset->insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50)); + stdmultiset->insert(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boost::make_move_iterator(&aux_vect[0])..." << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boost::make_move_iterator(&aux_vect3[0]), ..." << std::endl; + return 1; + } + + for(int i = 0, j = static_cast(boostset->size()); i < j; ++i){ + IntType erase_me(i); + boostset->erase(erase_me); + stdset->erase(i); + boostmultiset->erase(erase_me); + stdmultiset->erase(i); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->erase(erase_me)" << boostset->size() << " " << stdset->size() << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->erase(erase_me)" << std::endl; + return 1; + } + } + } + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + IntType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect3[i] = boost::move(move_me); + } + + IntType aux_vect4[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect4[i] = boost::move(move_me); + } + + IntType aux_vect5[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect5[i] = boost::move(move_me); + } + + boostset->insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(aux_vect + 50)); + boostset->insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50)); + stdset->insert(aux_vect2, aux_vect2 + 50); + stdset->insert(aux_vect2, aux_vect2 + 50); + boostmultiset->insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(aux_vect4 + 50)); + boostmultiset->insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(aux_vect5 + 50)); + stdmultiset->insert(aux_vect2, aux_vect2 + 50); + stdmultiset->insert(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boost::make_move_iterator(&aux_vect5[0])..." << std::endl; + return 1; + } + + boostset->erase(*boostset->begin()); + stdset->erase(*stdset->begin()); + boostmultiset->erase(*boostmultiset->begin()); + stdmultiset->erase(*stdmultiset->begin()); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->erase(*boostset->begin())" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->erase(*boostmultiset->begin())" << std::endl; + return 1; + } + } + + for(i = 0; i < max; ++i){ + IntType move_me(i); + boostset->insert(boost::move(move_me)); + stdset->insert(i); + IntType move_me2(i); + boostmultiset->insert(boost::move(move_me2)); + stdmultiset->insert(i); + } + + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boost::move(move_me)) try 2" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boost::move(move_me2)) try 2" << std::endl; + return 1; + } + + for(i = 0; i < max; ++i){ + IntType move_me(i); + boostset->insert(boostset->begin(), boost::move(move_me)); + stdset->insert(stdset->begin(), i); + //PrintContainers(boostset, stdset); + IntType move_me2(i); + boostmultiset->insert(boostmultiset->begin(), boost::move(move_me2)); + stdmultiset->insert(stdmultiset->begin(), i); + //PrintContainers(boostmultiset, stdmultiset); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boostset->begin(), boost::move(move_me))" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boostmultiset->begin(), boost::move(move_me2))" << std::endl; + return 1; + } + + IntType move_me3(i); + boostset->insert(boostset->end(), boost::move(move_me3)); + stdset->insert(stdset->end(), i); + IntType move_me4(i); + boostmultiset->insert(boostmultiset->end(), boost::move(move_me4)); + stdmultiset->insert(stdmultiset->end(), i); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boostset->end(), boost::move(move_me3))" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boostmultiset->end(), boost::move(move_me4))" << std::endl; + return 1; + } + { + IntType move_me(i); + boostset->insert(boostset->upper_bound(move_me), boost::move(move_me)); + stdset->insert(stdset->upper_bound(i), i); + //PrintContainers(boostset, stdset); + IntType move_me2(i); + boostmultiset->insert(boostmultiset->upper_bound(move_me2), boost::move(move_me2)); + stdmultiset->insert(stdmultiset->upper_bound(i), i); + //PrintContainers(boostmultiset, stdmultiset); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boostset->upper_bound(move_me), boost::move(move_me))" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boostmultiset->upper_bound(move_me2), boost::move(move_me2))" << std::endl; + return 1; + } + + } + { + IntType move_me(i); + boostset->insert(boostset->lower_bound(move_me), boost::move(move_me2)); + stdset->insert(stdset->lower_bound(i), i); + //PrintContainers(boostset, stdset); + IntType move_me2(i); + boostmultiset->insert(boostmultiset->lower_bound(move_me2), boost::move(move_me2)); + stdmultiset->insert(stdmultiset->lower_bound(i), i); + //PrintContainers(boostmultiset, stdmultiset); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset->insert(boostset->lower_bound(move_me), boost::move(move_me2))" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset->insert(boostmultiset->lower_bound(move_me2), boost::move(move_me2))" << std::endl; + return 1; + } + } + } + + //Compare count with std containers + for(i = 0; i < max; ++i){ + IntType count_me(i); + if(boostset->count(count_me) != stdset->count(i)){ + return -1; + } + if(boostmultiset->count(count_me) != stdmultiset->count(i)){ + return -1; + } + } + + //Now do count exercise + boostset->erase(boostset->begin(), boostset->end()); + boostmultiset->erase(boostmultiset->begin(), boostmultiset->end()); + boostset->clear(); + boostmultiset->clear(); + + for(j = 0; j < 3; ++j) + for(i = 0; i < 100; ++i){ + IntType move_me(i); + boostset->insert(boost::move(move_me)); + IntType move_me2(i); + boostmultiset->insert(boost::move(move_me2)); + IntType count_me(i); + if(boostset->count(count_me) != typename MyBoostMultiSet::size_type(1)){ + std::cout << "Error in boostset->count(count_me)" << std::endl; + return 1; + } + if(boostmultiset->count(count_me) != typename MyBoostMultiSet::size_type(j+1)){ + std::cout << "Error in boostmultiset->count(count_me)" << std::endl; + return 1; + } + } + + delete boostset; + delete stdset; + delete boostmultiset; + delete stdmultiset; + return 0; +} + +template +int set_test_copyable () +{ + typedef typename MyBoostSet::value_type IntType; + const int max = 100; + + try{ + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyBoostSet *boostset = new MyBoostSet; + MyStdSet *stdset = new MyStdSet; + MyBoostMultiSet *boostmultiset = new MyBoostMultiSet; + MyStdMultiSet *stdmultiset = new MyStdMultiSet; + + int i; + for(i = 0; i < max; ++i){ + IntType move_me(i); + boostset->insert(boost::move(move_me)); + stdset->insert(i); + IntType move_me2(i); + boostmultiset->insert(boost::move(move_me2)); + stdmultiset->insert(i); + } + if(!CheckEqualContainers(boostset, stdset)) return 1; + if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1; + + { + //Now, test copy constructor + MyBoostSet boostsetcopy(*boostset); + MyStdSet stdsetcopy(*stdset); + + if(!CheckEqualContainers(&boostsetcopy, &stdsetcopy)) + return 1; + + MyBoostMultiSet boostmsetcopy(*boostmultiset); + MyStdMultiSet stdmsetcopy(*stdmultiset); + + if(!CheckEqualContainers(&boostmsetcopy, &stdmsetcopy)) + return 1; + + //And now assignment + boostsetcopy = *boostset; + stdsetcopy = *stdset; + + if(!CheckEqualContainers(&boostsetcopy, &stdsetcopy)) + return 1; + + boostmsetcopy = *boostmultiset; + stdmsetcopy = *stdmultiset; + + if(!CheckEqualContainers(&boostmsetcopy, &stdmsetcopy)) + return 1; + } + delete boostset; + delete boostmultiset; + } + catch(...){ + throw; + } + return 0; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include + +#endif diff --git a/test/slist_test.cpp b/test/slist_test.cpp new file mode 100644 index 0000000..e18f0bb --- /dev/null +++ b/test/slist_test.cpp @@ -0,0 +1,82 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" +#include "emplace_test.hpp" + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +template class boost::container::slist >; + +typedef slist MyList; +typedef slist MyMoveList; +typedef slist MyCopyMoveList; +typedef slist MyCopyList; + +class recursive_slist +{ +public: + int id_; + slist slist_; + recursive_slist &operator=(const recursive_slist &o) + { slist_ = o.slist_; return *this; } +}; + +void recursive_slist_test()//Test for recursive types +{ + slist recursive_list_list; +} + +int main () +{ + recursive_slist_test(); + { + //Now test move semantics + slist original; + slist move_ctor(boost::move(original)); + slist move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + { + slist recursive, copy; + //Test to test both move emulations + if(!copy.size()){ + copy = recursive; + } + } + } + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + const test::EmplaceOptions Options = (test::EmplaceOptions) + (test::EMPLACE_FRONT | test::EMPLACE_AFTER | test::EMPLACE_BEFORE | test::EMPLACE_AFTER); + + if(!boost::container::test::test_emplace + < slist, Options>()) + return 1; +} + +#include + diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp new file mode 100644 index 0000000..bf42978 --- /dev/null +++ b/test/stable_vector_test.cpp @@ -0,0 +1,86 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include +#include "check_equal_containers.hpp" +#include "movable_int.hpp" +#include "expand_bwd_test_allocator.hpp" +#include "expand_bwd_test_template.hpp" +#include "dummy_test_allocator.hpp" +#include "vector_test.hpp" + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +//template class stable_vector >; + +class recursive_vector +{ + public: + int id_; + stable_vector vector_; + recursive_vector &operator=(const recursive_vector &o) + { vector_ = o.vector_; return *this; } +}; + +void recursive_vector_test()//Test for recursive types +{ + stable_vector recursive, copy; + //Test to test both move emulations + if(!copy.size()){ + copy = recursive; + } +} + +int main() +{ + recursive_vector_test(); + { + //Now test move semantics + stable_vector original; + stable_vector move_ctor(boost::move(original)); + stable_vector move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + typedef stable_vector MyVector; + typedef stable_vector MyMoveVector; + typedef stable_vector MyCopyMoveVector; + typedef stable_vector MyCopyVector; + + if(test::vector_test()) + return 1; + + if(test::vector_test()) + return 1; + + if(test::vector_test()) + return 1; + + if(test::vector_test()) + return 1; + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE); + if(!boost::container::test::test_emplace + < stable_vector, Options>()) + return 1; + + return 0; +} + +#include diff --git a/test/string_test.cpp b/test/string_test.cpp new file mode 100644 index 0000000..8c873ce --- /dev/null +++ b/test/string_test.cpp @@ -0,0 +1,293 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dummy_test_allocator.hpp" +#include "check_equal_containers.hpp" +#include "expand_bwd_test_allocator.hpp" +#include "expand_bwd_test_template.hpp" + +using namespace boost::container; + +typedef test::dummy_test_allocator DummyCharAllocator; +typedef basic_string, DummyCharAllocator> DummyString; +typedef test::dummy_test_allocator DummyStringAllocator; +typedef test::dummy_test_allocator DummyWCharAllocator; +typedef basic_string, DummyWCharAllocator> DummyWString; +typedef test::dummy_test_allocator DummyWStringAllocator; + +//Explicit instantiations of container::basic_string +template class basic_string, DummyCharAllocator>; +template class basic_string, DummyWCharAllocator>; +//Explicit instantiation of container::vectors of container::strings +template class vector; +template class vector; + +struct StringEqual +{ + template + bool operator ()(const Str1 &string1, const Str2 &string2) const + { + if(string1.size() != string2.size()) + return false; + return std::char_traits::compare + (string1.c_str(), string2.c_str(), string1.size()) == 0; + } +}; + +//Function to check if both lists are equal +template +bool CheckEqualStringVector(StrVector1 *strvect1, StrVector2 *strvect2) +{ + StringEqual comp; + return std::equal(strvect1->begin(), strvect1->end(), + strvect2->begin(), comp); +} + +template +int string_test() +{ + typedef std::string StdString; + typedef vector StdStringVector; + typedef basic_string BoostString; + typedef vector BoostStringVector; + + const int MaxSize = 100; + + //Create shared memory + { + BoostStringVector *boostStringVect = new BoostStringVector; + StdStringVector *stdStringVect = new StdStringVector; + BoostString auxBoostString; + StdString auxStdString(StdString(auxBoostString.begin(), auxBoostString.end() )); + + CharType buffer [20]; + + //First, push back + for(int i = 0; i < MaxSize; ++i){ + auxBoostString = "String"; + auxStdString = "String"; + std::sprintf(buffer, "%i", i); + auxBoostString += buffer; + auxStdString += buffer; + boostStringVect->push_back(auxBoostString); + stdStringVect->push_back(auxStdString); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)){ + return 1; + } + + //Now push back moving + for(int i = 0; i < MaxSize; ++i){ + auxBoostString = "String"; + auxStdString = "String"; + std::sprintf(buffer, "%i", i); + auxBoostString += buffer; + auxStdString += buffer; + boostStringVect->push_back(boost::move(auxBoostString)); + stdStringVect->push_back(auxStdString); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)){ + return 1; + } + + //push front + for(int i = 0; i < MaxSize; ++i){ + auxBoostString = "String"; + auxStdString = "String"; + std::sprintf(buffer, "%i", i); + auxBoostString += buffer; + auxStdString += buffer; + boostStringVect->insert(boostStringVect->begin(), auxBoostString); + stdStringVect->insert(stdStringVect->begin(), auxStdString); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)){ + return 1; + } + + //Now push front moving + for(int i = 0; i < MaxSize; ++i){ + auxBoostString = "String"; + auxStdString = "String"; + std::sprintf(buffer, "%i", i); + auxBoostString += buffer; + auxStdString += buffer; + boostStringVect->insert(boostStringVect->begin(), boost::move(auxBoostString)); + stdStringVect->insert(stdStringVect->begin(), auxStdString); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)){ + return 1; + } + + //Now test long and short representation swapping + + //Short first + auxBoostString = "String"; + auxStdString = "String"; + BoostString boost_swapper; + StdString std_swapper; + boost_swapper.swap(auxBoostString); + std_swapper.swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + if(!StringEqual()(boost_swapper, std_swapper)) + return 1; + boost_swapper.swap(auxBoostString); + std_swapper.swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + if(!StringEqual()(boost_swapper, std_swapper)) + return 1; + + //Shrink_to_fit + auxBoostString.shrink_to_fit(); + StdString(auxStdString).swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + //Reserve + shrink_to_fit + auxBoostString.reserve(boost_swapper.size()*2+1); + auxStdString.reserve(std_swapper.size()*2+1); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + auxBoostString.shrink_to_fit(); + StdString(auxStdString).swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + //Long string + auxBoostString = "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; + auxStdString = "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; + boost_swapper = BoostString(); + std_swapper = StdString(); + boost_swapper.swap(auxBoostString); + std_swapper.swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + if(!StringEqual()(boost_swapper, std_swapper)) + return 1; + boost_swapper.swap(auxBoostString); + std_swapper.swap(auxStdString); + + //Shrink_to_fit + auxBoostString.shrink_to_fit(); + StdString(auxStdString).swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + auxBoostString.clear(); + auxStdString.clear(); + auxBoostString.shrink_to_fit(); + StdString(auxStdString).swap(auxStdString); + if(!StringEqual()(auxBoostString, auxStdString)) + return 1; + + //No sort + std::sort(boostStringVect->begin(), boostStringVect->end()); + std::sort(stdStringVect->begin(), stdStringVect->end()); + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + const CharType prefix [] = "Prefix"; + const int prefix_size = sizeof(prefix)/sizeof(prefix[0])-1; + const CharType sufix [] = "Suffix"; + + for(int i = 0; i < MaxSize; ++i){ + (*boostStringVect)[i].append(sufix); + (*stdStringVect)[i].append(sufix); + (*boostStringVect)[i].insert((*boostStringVect)[i].begin(), + prefix, prefix + prefix_size); + (*stdStringVect)[i].insert((*stdStringVect)[i].begin(), + prefix, prefix + prefix_size); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + for(int i = 0; i < MaxSize; ++i){ + std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end()); + std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end()); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + for(int i = 0; i < MaxSize; ++i){ + std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end()); + std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end()); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + for(int i = 0; i < MaxSize; ++i){ + std::sort(boostStringVect->begin(), boostStringVect->end()); + std::sort(stdStringVect->begin(), stdStringVect->end()); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + for(int i = 0; i < MaxSize; ++i){ + (*boostStringVect)[i].replace((*boostStringVect)[i].begin(), + (*boostStringVect)[i].end(), + "String"); + (*stdStringVect)[i].replace((*stdStringVect)[i].begin(), + (*stdStringVect)[i].end(), + "String"); + } + + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + boostStringVect->erase(std::unique(boostStringVect->begin(), boostStringVect->end()), + boostStringVect->end()); + stdStringVect->erase(std::unique(stdStringVect->begin(), stdStringVect->end()), + stdStringVect->end()); + if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1; + + //When done, delete vector + delete boostStringVect; + delete stdStringVect; + } + return 0; +} + +bool test_expand_bwd() +{ + //Now test all back insertion possibilities + typedef test::expand_bwd_test_allocator + allocator_type; + typedef basic_string, allocator_type> + string_type; + return test::test_all_expand_bwd(); +} + +int main() +{ + if(string_test()){ + return 1; + } + + if(!test_expand_bwd()) + return 1; + + return 0; +} + +#include diff --git a/test/tree_test.cpp b/test/tree_test.cpp new file mode 100644 index 0000000..0df3ac4 --- /dev/null +++ b/test/tree_test.cpp @@ -0,0 +1,233 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include "print_container.hpp" +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" +#include "set_test.hpp" +#include "map_test.hpp" +#include "emplace_test.hpp" + +using namespace boost::container; + +//Alias standard types +typedef std::set MyStdSet; +typedef std::multiset MyStdMultiSet; +typedef std::map MyStdMap; +typedef std::multimap MyStdMultiMap; + +//Alias non-movable types +typedef set MyBoostSet; +typedef multiset MyBoostMultiSet; +typedef map MyBoostMap; +typedef multimap MyBoostMultiMap; + +//Alias movable types +typedef set MyMovableBoostSet; +typedef multiset MyMovableBoostMultiSet; +typedef map MyMovableBoostMap; +typedef multimap MyMovableBoostMultiMap; +typedef set MyMoveCopyBoostSet; +typedef set MyCopyBoostSet; +typedef multiset MyMoveCopyBoostMultiSet; +typedef multiset MyCopyBoostMultiSet; +typedef map MyMoveCopyBoostMap; +typedef multimap MyMoveCopyBoostMultiMap; +typedef map MyCopyBoostMap; +typedef multimap MyCopyBoostMultiMap; +//Test recursive structures +class recursive_set +{ +public: + int id_; + set set_; + friend bool operator< (const recursive_set &a, const recursive_set &b) + { return a.id_ < b.id_; } +}; + +class recursive_map +{ + public: + int id_; + map map_; + friend bool operator< (const recursive_map &a, const recursive_map &b) + { return a.id_ < b.id_; } +}; + +//Test recursive structures +class recursive_multiset +{ +public: + int id_; + multiset multiset_; + friend bool operator< (const recursive_multiset &a, const recursive_multiset &b) + { return a.id_ < b.id_; } +}; + +class recursive_multimap +{ +public: + int id_; + multimap multimap_; + friend bool operator< (const recursive_multimap &a, const recursive_multimap &b) + { return a.id_ < b.id_; } +}; + +template +void test_move() +{ + //Now test move semantics + C original; + C move_ctor(boost::move(original)); + C move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); +} + +int main () +{ + //Recursive container instantiation + { + set set_; + multiset multiset_; + map map_; + multimap multimap_; + } + //Now test move semantics + { + test_move >(); + test_move >(); + test_move >(); + test_move >(); + } + + //using namespace boost::container::detail; + + if(0 != test::set_test()){ + return 1; + } + + if(0 != test::set_test_copyable()){ + return 1; + } + + if(0 != test::set_test()){ + return 1; + } + + if(0 != test::set_test()){ + return 1; + } + + if(0 != test::set_test_copyable()){ + return 1; + } + + if(0 != test::set_test()){ + return 1; + } + + if(0 != test::set_test_copyable()){ + return 1; + } + + if (0 != test::map_test()){ + return 1; + } + + if(0 != test::map_test_copyable()){ + return 1; + } + +// if (0 != test::map_test()){ +// return 1; +// } + + if (0 != test::map_test()){ + return 1; + } + + if (0 != test::map_test_copyable()){ + return 1; + } + + if (0 != test::map_test()){ + return 1; + } + + if (0 != test::map_test_copyable()){ + return 1; + } + + const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC); + if(!boost::container::test::test_emplace, SetOptions>()) + return 1; + if(!boost::container::test::test_emplace, SetOptions>()) + return 1; + const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR); + if(!boost::container::test::test_emplace, MapOptions>()) + return 1; + if(!boost::container::test::test_emplace, MapOptions>()) + return 1; + + return 0; +} + +#include diff --git a/test/util.hpp b/test/util.hpp new file mode 100644 index 0000000..eea3b00 --- /dev/null +++ b/test/util.hpp @@ -0,0 +1,113 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_CONTAINER_TEST_UTIL_HEADER +#define BOOST_CONTAINER_TEST_UTIL_HEADER + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef DEFAULT_EXECUTION_MONITOR_TYPE +# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition +#endif + +namespace boost { +namespace container { +namespace test { + +inline void sleep(const boost::posix_time::ptime &xt) +{ + boost::container::container_mutex mx; + boost::container::scoped_lock + lock(mx); + boost::container::container_condition cond; + cond.timed_wait(lock, xt); +} + +inline boost::posix_time::ptime delay(int secs, int msecs=0, int nsecs = 0) +{ + (void)msecs; + using namespace boost::posix_time; + int count = static_cast(double(nsecs)* + (double(time_duration::ticks_per_second())/double(1000000000.0))); + count += static_cast(double(msecs)* + (double(time_duration::ticks_per_second())/double(1000.0))); + boost::posix_time::ptime cur = microsec_clock::universal_time(); + return cur += boost::posix_time::time_duration(0, 0, secs, count); +} + +inline bool in_range(const boost::posix_time::ptime& xt, int secs=1) +{ + boost::posix_time::ptime min = delay(-secs); + boost::posix_time::ptime max = delay(0); + return (xt > min) && (max > xt); +} + +boost::xtime xsecs(int secs) +{ + boost::xtime ret; + boost::xtime_get(&ret, boost::TIME_UTC); + ret.sec += secs; + return ret; +} + +template +class thread_adapter +{ + public: + thread_adapter(void (*func)(void*, P &), void* param1, P ¶m2) + : _func(func), _param1(param1) ,_param2(param2){ } + void operator()() const { _func(_param1, _param2); } + + private: + void (*_func)(void*, P &); + void* _param1; + P& _param2; +}; + +template +struct data +{ + data(int id, int secs=0) + : m_id(id), m_value(-1), m_secs(secs) + {} + int m_id; + int m_value; + int m_secs; +}; + +static int shared_val = 0; +static const int BaseSeconds = 1; + +} //namespace test { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINER_TEST_UTIL_HEADER diff --git a/test/vector_test.cpp b/test/vector_test.cpp new file mode 100644 index 0000000..9bdc584 --- /dev/null +++ b/test/vector_test.cpp @@ -0,0 +1,127 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include +#include "check_equal_containers.hpp" +#include "movable_int.hpp" +#include "expand_bwd_test_allocator.hpp" +#include "expand_bwd_test_template.hpp" +#include "dummy_test_allocator.hpp" +#include "vector_test.hpp" + +using namespace boost::container; + +//Explicit instantiation to detect compilation errors +template class boost::container::vector >; + +int test_expand_bwd() +{ + //Now test all back insertion possibilities + + //First raw ints + typedef test::expand_bwd_test_allocator + int_allocator_type; + typedef vector + int_vector; + + if(!test::test_all_expand_bwd()) + return 1; + + //Now user defined wrapped int + typedef test::expand_bwd_test_allocator + int_holder_allocator_type; + typedef vector + int_holder_vector; + + if(!test::test_all_expand_bwd()) + return 1; + + //Now user defined bigger wrapped int + typedef test::expand_bwd_test_allocator + triple_int_holder_allocator_type; + + typedef vector + triple_int_holder_vector; + + if(!test::test_all_expand_bwd()) + return 1; + + return 0; +} + +class recursive_vector +{ + public: + int id_; + vector vector_; +}; + +void recursive_vector_test()//Test for recursive types +{ + vector recursive_vector_vector; +} + +enum Test +{ + zero, one, two, three, four, five, six +}; + + +int main() +{ + recursive_vector_test(); + { + //Now test move semantics + vector original; + vector move_ctor(boost::move(original)); + vector move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + typedef vector MyVector; + typedef vector MyMoveVector; + typedef vector MyCopyMoveVector; + typedef vector MyCopyVector; + typedef vector MyEnumVector; + + + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + if(test_expand_bwd()) + return 1; + + MyEnumVector v; + Test t; + v.push_back(t); + v.push_back(::boost::move(t)); + v.push_back(Test()); + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE); + if(!boost::container::test::test_emplace + < vector, Options>()) + return 1; + + return 0; +} +#include diff --git a/test/vector_test.hpp b/test/vector_test.hpp new file mode 100644 index 0000000..c57700e --- /dev/null +++ b/test/vector_test.hpp @@ -0,0 +1,253 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "print_container.hpp" +#include "check_equal_containers.hpp" +#include "movable_int.hpp" +#include +#include +#include "emplace_test.hpp" + +namespace boost{ +namespace container { +namespace test{ + +template +bool vector_copyable_only(V1 *, V2 *, boost::container::containers_detail::false_type) +{ + return true; +} + +//Function to check if both sets are equal +template +bool vector_copyable_only(V1 *boostvector, V2 *stdvector, boost::container::containers_detail::true_type) +{ + typedef typename V1::value_type IntType; + std::size_t size = boostvector->size(); + boostvector->insert(boostvector->end(), 50, IntType(1)); + stdvector->insert(stdvector->end(), 50, 1); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + + { + IntType move_me(1); + boostvector->insert(boostvector->begin()+size/2, 50, boost::move(move_me)); + stdvector->insert(stdvector->begin()+size/2, 50, 1); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + } + { + IntType move_me(2); + boostvector->assign(boostvector->size()/2, boost::move(move_me)); + stdvector->assign(stdvector->size()/2, 2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + } + { + IntType move_me(3); + boostvector->assign(boostvector->size()*3-1, boost::move(move_me)); + stdvector->assign(stdvector->size()*3-1, 3); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + } + + { + IntType copy_me(3); + const IntType ccopy_me(3); + boostvector->push_back(copy_me); + stdvector->push_back(int(3)); + boostvector->push_back(ccopy_me); + stdvector->push_back(int(3)); + if(!test::CheckEqualContainers(boostvector, stdvector)) return false; + } + + return true; +} + +template +int vector_test() +{ + typedef std::vector MyStdVector; + typedef typename MyBoostVector::value_type IntType; + const int max = 100; + + { + try{ + MyBoostVector *boostvector = new MyBoostVector; + MyStdVector *stdvector = new MyStdVector; + boostvector->resize(100); + stdvector->resize(100); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->resize(200); + stdvector->resize(200); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->resize(0); + stdvector->resize(0); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + for(int i = 0; i < max; ++i){ + IntType new_int(i); + boostvector->insert(boostvector->end(), boost::move(new_int)); + stdvector->insert(stdvector->end(), i); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + } + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + typename MyBoostVector::iterator boostit(boostvector->begin()); + typename MyStdVector::iterator stdit(stdvector->begin()); + typename MyBoostVector::const_iterator cboostit = boostit; + ++boostit; ++stdit; + boostvector->erase(boostit); + stdvector->erase(stdit); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->erase(boostvector->begin()); + stdvector->erase(stdvector->begin()); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + { + //Initialize values + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType new_int(-1); + BOOST_STATIC_ASSERT((boost::container::test::is_copyable::value == false)); + aux_vect[i] = boost::move(new_int); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + + boostvector->insert(boostvector->end() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(aux_vect + 50)); + stdvector->insert(stdvector->end(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + for(int i = 0, j = static_cast(boostvector->size()); i < j; ++i){ + boostvector->erase(boostvector->begin()); + stdvector->erase(stdvector->begin()); + } + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + } + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType new_int(-1); + aux_vect[i] = boost::move(new_int); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + boostvector->insert(boostvector->begin() + ,boost::make_move_iterator(&aux_vect[0]) + ,boost::make_move_iterator(aux_vect + 50)); + stdvector->insert(stdvector->begin(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + } +/* + boostvector->reserve(boostvector->size()*2); + stdvector->reserve(stdvector->size()*2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; +*/ + boostvector->shrink_to_fit(); + MyStdVector(*stdvector).swap(*stdvector); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->shrink_to_fit(); + MyStdVector(*stdvector).swap(*stdvector); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + IntType push_back_this(1); + boostvector->push_back(boost::move(push_back_this)); + stdvector->push_back(int(1)); + boostvector->push_back(IntType(1)); + stdvector->push_back(int(1)); + + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + if(!vector_copyable_only(boostvector, stdvector + ,containers_detail::bool_::value>())){ + return 1; + } + + boostvector->erase(boostvector->begin()); + stdvector->erase(stdvector->begin()); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + for(int i = 0; i < max; ++i){ + IntType insert_this(i); + boostvector->insert(boostvector->begin(), boost::move(insert_this)); + stdvector->insert(stdvector->begin(), i); + boostvector->insert(boostvector->begin(), IntType(i)); + stdvector->insert(stdvector->begin(), int(i)); + } + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + //Test insertion from list + { + std::list l(50, int(1)); + boostvector->insert(boostvector->begin(), l.begin(), l.end()); + stdvector->insert(stdvector->begin(), l.begin(), l.end()); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + boostvector->assign(l.begin(), l.end()); + stdvector->assign(l.begin(), l.end()); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + } +/* + std::size_t cap = boostvector->capacity(); + boostvector->reserve(cap*2); + stdvector->reserve(cap*2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + boostvector->resize(0); + stdvector->resize(0); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->resize(cap*2); + stdvector->resize(cap*2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->clear(); + stdvector->clear(); + boostvector->shrink_to_fit(); + MyStdVector(*stdvector).swap(*stdvector); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; + + boostvector->resize(cap*2); + stdvector->resize(cap*2); + if(!test::CheckEqualContainers(boostvector, stdvector)) return 1; +*/ + + delete stdvector; + delete boostvector; + } + catch(std::exception &ex){ + std::cout << ex.what() << std::endl; + return 1; + } + } + std::cout << std::endl << "Test OK!" << std::endl; + return 0; +} + +} //namespace test{ +} //namespace container { +} //namespace boost{ + +#include