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 0000000..764bf4f Binary files /dev/null and b/doc/html/images/blank.png differ diff --git a/doc/html/images/caution.png b/doc/html/images/caution.png new file mode 100644 index 0000000..5b7809c Binary files /dev/null and b/doc/html/images/caution.png differ diff --git a/doc/html/images/draft.png b/doc/html/images/draft.png new file mode 100644 index 0000000..0084708 Binary files /dev/null and b/doc/html/images/draft.png differ diff --git a/doc/html/images/home.png b/doc/html/images/home.png new file mode 100644 index 0000000..5584aac Binary files /dev/null and b/doc/html/images/home.png differ diff --git a/doc/html/images/important.png b/doc/html/images/important.png new file mode 100644 index 0000000..12c90f6 Binary files /dev/null and b/doc/html/images/important.png differ diff --git a/doc/html/images/next.png b/doc/html/images/next.png new file mode 100644 index 0000000..59800b4 Binary files /dev/null and b/doc/html/images/next.png differ diff --git a/doc/html/images/note.png b/doc/html/images/note.png new file mode 100644 index 0000000..d0c3c64 Binary files /dev/null and b/doc/html/images/note.png differ diff --git a/doc/html/images/prev.png b/doc/html/images/prev.png new file mode 100644 index 0000000..d88a40f Binary files /dev/null and b/doc/html/images/prev.png differ diff --git a/doc/html/images/stable_vector.png b/doc/html/images/stable_vector.png new file mode 100644 index 0000000..26af7af Binary files /dev/null and b/doc/html/images/stable_vector.png differ diff --git a/doc/html/images/tip.png b/doc/html/images/tip.png new file mode 100644 index 0000000..5c4aab3 Binary files /dev/null and b/doc/html/images/tip.png differ diff --git a/doc/html/images/toc-blank.png b/doc/html/images/toc-blank.png new file mode 100644 index 0000000..6ffad17 Binary files /dev/null and b/doc/html/images/toc-blank.png differ diff --git a/doc/html/images/toc-minus.png b/doc/html/images/toc-minus.png new file mode 100644 index 0000000..abbb020 Binary files /dev/null and b/doc/html/images/toc-minus.png differ diff --git a/doc/html/images/toc-plus.png b/doc/html/images/toc-plus.png new file mode 100644 index 0000000..941312c Binary files /dev/null and b/doc/html/images/toc-plus.png differ diff --git a/doc/html/images/up.png b/doc/html/images/up.png new file mode 100644 index 0000000..17d9c3e Binary files /dev/null and b/doc/html/images/up.png differ diff --git a/doc/html/images/warning.png b/doc/html/images/warning.png new file mode 100644 index 0000000..1c33db8 Binary files /dev/null and b/doc/html/images/warning.png differ 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