STL
Many thanks to the people who devote themselft to the common libs.
STL four components
Global Constructor and Destructor
STL Allocator
STL Vector
STL List
STL Tree
asdfsdf
Introduction to the Standard Template Library.
- The Standard Template Library ( abbreviated as STL ) is a C++ library consisting of three components which are container classes, algorithms, and iterators providing many of the basic algorithms and data structures and data accessing easily of computer science.
- You should make sure that you understand how templates work with C++ before you use the STL.
- Templates = replacement = code expansion at compiling-time.
- Like many class library, The STL includes container classes whose purpose is to contain other objects, including the classes:vector, list, deque, set, multiset, map, multimap, hash_set, hash_multiset, hash_map and hash_multimap.
- The STL also includes a large collection of algorithms that manipulate the data stored in containers.
- There are two important points to notice about this call to reverse(). First, it is a global function, not a member function. Second, it takes two arguments rather than one: it operates on a range of elements, rather than on a container. In this particular case the range happens to be the entire container.
- reverse( objectOfcontainer.begin(), objectOfcontainer.end())
- Iterators are the mechanism that makes it possible to decouple algorithms from containers: algorithms are templates, and are parameterized by the type of iterator, so they are not restricted to a single type of container. Traverse all element in container.
- Proceed from the beginning to the end, and stops either when it finds an iterator that points to value or when it reaches the end of the range.
- One very important question to ask about any template function, not just about STL algorithms is what the set of types is that may correctly be substituted for the formal template parameters.
- Concepts are not a part of the C++ language; there is no way to declare a concept in a program, or to declare that particular type is a model of a concept. Nevertheless, concepts are an extremely important part of the STL. Using concepts makes it possible to write programs that cleanly separate interface from implementation.
- Concept programming, Generic programming
Classification of STL components
- The STL components are divided into six broad categories on the basis of functionality: Containers, Iterator, Algorithms, Function Objects, Utilities, and Allocator.
- The STL documentation contains two indices ( index). One of them, the Main Index, list all components in alphabetical order. The other, the Divided Index, contains a separate alphabetical listing for each category.
- The format of a concept page. A page that documents a concept has the following sections: Summary; Refinement of; Associated types; Notation; Definitions; Valid Expressions; Expression Semantics; Complexity Guarantees; Invariants; Models; Notes; See Also;
-
1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Pablo Halpern 2009. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 ////////////////////////////////////////////////////////////////////////////// 8 // 9 // (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost 10 // Software License, Version 1.0. (See accompanying file 11 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 // 13 // See http://www.boost.org/libs/container for documentation. 14 // 15 ////////////////////////////////////////////////////////////////////////////// 16 17 #ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP 18 #define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP 19 20 #if (defined _MSC_VER) && (_MSC_VER >= 1200) 21 # pragma once 22 #endif 23 #include <boost/container/detail/config_begin.hpp> 24 #include <boost/container/detail/workaround.hpp> 25 #include <boost/intrusive/pointer_traits.hpp> 26 #include <boost/intrusive/detail/memory_util.hpp> 27 #include <boost/container/detail/memory_util.hpp> 28 #include <boost/type_traits/integral_constant.hpp> 29 #include <boost/container/detail/mpl.hpp> 30 #include <boost/move/utility.hpp> 31 #include <limits> //numeric_limits<>::max() 32 #include <new> //placement new 33 #include <memory> //std::allocator 34 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 35 #include <boost/container/detail/preprocessor.hpp> 36 #endif 37 38 namespace boost { 39 namespace container { 40 namespace container_detail { 41 42 template<class A> 43 struct is_std_allocator 44 { static const bool value = false; }; 45 46 template<class T> 47 struct is_std_allocator< std::allocator<T> > 48 { static const bool value = true; }; 49 50 } //namespace container_detail { 51 52 template <typename Alloc> 53 struct allocator_traits 54 { 55 //allocator_type 56 typedef Alloc allocator_type; 57 //value_type 58 typedef typename Alloc::value_type value_type; 59 60 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 61 62 typedef unspecified pointer; 63 typedef see_documentation const_pointer; 64 typedef see_documentation reference; 65 typedef see_documentation const_reference; 66 typedef see_documentation void_pointer; 67 typedef see_documentation const_void_pointer; 68 typedef see_documentation difference_type; 69 typedef see_documentation size_type; 70 typedef see_documentation propagate_on_container_copy_assignment; 71 typedef see_documentation propagate_on_container_move_assignment; 72 typedef see_documentation propagate_on_container_swap; 73 template <class T> using rebind_alloc = see_documentation; 74 template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >; 75 template <class T> 76 struct portable_rebind_alloc 77 { typedef see_documentation type; }; 78 #else 79 //pointer 80 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 81 pointer, value_type*) 82 pointer; 83 //const_pointer 84 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, 85 const_pointer, typename boost::intrusive::pointer_traits<pointer>::template 86 rebind_pointer<const value_type>) 87 const_pointer; 88 //reference 89 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 90 reference, typename container_detail::unvoid<value_type>::type&) 91 reference; 92 //const_reference 93 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 94 const_reference, const typename container_detail::unvoid<value_type>::type&) 95 const_reference; 96 //void_pointer 97 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, 98 void_pointer, typename boost::intrusive::pointer_traits<pointer>::template 99 rebind_pointer<void>) 100 void_pointer; 101 //const_void_pointer 102 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, 103 const_void_pointer, typename boost::intrusive::pointer_traits<pointer>::template 104 rebind_pointer<const void>) 105 const_void_pointer; 106 //difference_type 107 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 108 difference_type, std::ptrdiff_t) 109 difference_type; 110 //size_type 111 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 112 size_type, std::size_t) 113 size_type; 114 //propagate_on_container_copy_assignment 115 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 116 propagate_on_container_copy_assignment, boost::false_type) 117 propagate_on_container_copy_assignment; 118 //propagate_on_container_move_assignment 119 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 120 propagate_on_container_move_assignment, boost::false_type) 121 propagate_on_container_move_assignment; 122 //propagate_on_container_swap 123 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, 124 propagate_on_container_swap, boost::false_type) 125 propagate_on_container_swap; 126 127 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 128 //C++11 129 template <typename T> using rebind_alloc = typename boost::intrusive::detail::type_rebinder<Alloc, T>::type; 130 template <typename T> using rebind_traits = allocator_traits< rebind_alloc<T> >; 131 #else // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 132 //Some workaround for C++03 or C++11 compilers with no template aliases 133 template <typename T> 134 struct rebind_alloc : boost::intrusive::detail::type_rebinder<Alloc,T>::type 135 { 136 typedef typename boost::intrusive::detail::type_rebinder<Alloc,T>::type Base; 137 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 138 template <typename... Args> 139 rebind_alloc(BOOST_FWD_REF(Args)... args) 140 : Base(boost::forward<Args>(args)...) 141 {} 142 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 143 #define BOOST_PP_LOCAL_MACRO(n) \ 144 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 145 rebind_alloc(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 146 : Base(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \ 147 {} \ 148 // 149 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) 150 #include BOOST_PP_LOCAL_ITERATE() 151 #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 152 }; 153 154 template <typename T> 155 struct rebind_traits 156 : allocator_traits<typename boost::intrusive::detail::type_rebinder<Alloc, T>::type> 157 {}; 158 #endif // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 159 template <class T> 160 struct portable_rebind_alloc 161 { typedef typename boost::intrusive::detail::type_rebinder<Alloc, T>::type type; }; 162 #endif //BOOST_CONTAINER_DOXYGEN_INVOKED 163 164 static pointer allocate(Alloc &a, size_type n) 165 { return a.allocate(n); } 166 167 static void deallocate(Alloc &a, pointer p, size_type n) 168 { a.deallocate(p, n); } 169 170 //! <b>Effects</b>: calls `a.allocate(n, p)` if that call is well-formed; 171 //! otherwise, invokes `a.allocate(n)` 172 static pointer allocate(Alloc &a, size_type n, const_void_pointer p) 173 { 174 const bool value = boost::container::container_detail:: 175 has_member_function_callable_with_allocate 176 <Alloc, const size_type, const const_void_pointer>::value; 177 ::boost::integral_constant<bool, value> flag; 178 return allocator_traits::priv_allocate(flag, a, n, p); 179 } 180 181 //! <b>Effects</b>: calls `a.destroy(p)` if that call is well-formed; 182 //! otherwise, invokes `p->~T()`. 183 template<class T> 184 static void destroy(Alloc &a, T*p) 185 { 186 typedef T* destroy_pointer; 187 const bool value = boost::container::container_detail:: 188 has_member_function_callable_with_destroy 189 <Alloc, const destroy_pointer>::value; 190 ::boost::integral_constant<bool, value> flag; 191 allocator_traits::priv_destroy(flag, a, p); 192 } 193 static size_type max_size(const Alloc &a) 194 { 195 const bool value = boost::container::container_detail:: 196 has_member_function_callable_with_max_size 197 <const Alloc>::value; 198 ::boost::integral_constant<bool, value> flag; 199 return allocator_traits::priv_max_size(flag, a); 200 } 201 202 static 203 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 204 typename container_detail::if_c 205 < boost::container::container_detail:: 206 has_member_function_callable_with_select_on_container_copy_construction 207 <const Alloc>::value 208 , Alloc 209 , const Alloc & 210 >::type 211 #else 212 Alloc 213 #endif 214 select_on_container_copy_construction(const Alloc &a) 215 { 216 const bool value = boost::container::container_detail:: 217 has_member_function_callable_with_select_on_container_copy_construction 218 <const Alloc>::value; 219 ::boost::integral_constant<bool, value> flag; 220 return allocator_traits::priv_select_on_container_copy_construction(flag, a); 221 } 222 template <class T, class ...Args> 223 static void construct(Alloc & a, T* p, BOOST_FWD_REF(Args)... args) 224 { 225 ::boost::integral_constant<bool, container_detail::is_std_allocator<Alloc>::value> flag; 226 allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...); 227 } 228 #endif 229 ///@cond 230 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 231 private: 232 static pointer priv_allocate(boost::true_type, Alloc &a, size_type n, const_void_pointer p) 233 { return a.allocate(n, p); } 234 235 static pointer priv_allocate(boost::false_type, Alloc &a, size_type n, const_void_pointer) 236 { return allocator_traits::allocate(a, n); } 237 238 template<class T> 239 static void priv_destroy(boost::true_type, Alloc &a, T* p) 240 { a.destroy(p); } 241 242 template<class T> 243 static void priv_destroy(boost::false_type, Alloc &, T* p) 244 { p->~T(); (void)p; } 245 246 static size_type priv_max_size(boost::true_type, const Alloc &a) 247 { return a.max_size(); } 248 249 static size_type priv_max_size(boost::false_type, const Alloc &) 250 { return (std::numeric_limits<size_type>::max)(); } 251 252 static Alloc priv_select_on_container_copy_construction(boost::true_type, const Alloc &a) 253 { return a.select_on_container_copy_construction(); } 254 255 static const Alloc &priv_select_on_container_copy_construction(boost::false_type, const Alloc &a) 256 { return a; } 257 258 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 259 template<class T, class ...Args> 260 static void priv_construct(boost::false_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) 261 { 262 const bool value = boost::container::container_detail:: 263 has_member_function_callable_with_construct 264 < Alloc, T*, Args... >::value; 265 ::boost::integral_constant<bool, value> flag; 266 priv_construct_dispatch2(flag, a, p, ::boost::forward<Args>(args)...); 267 } 268 269 template<class T, class ...Args> 270 static void priv_construct(boost::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) 271 { 272 priv_construct_dispatch2(boost::false_type(), a, p, ::boost::forward<Args>(args)...); 273 } 274 275 template<class T, class ...Args> 276 static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) 277 { a.construct( p, ::boost::forward<Args>(args)...); } 278 279 template<class T, class ...Args> 280 static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p, BOOST_FWD_REF(Args) ...args) 281 { ::new((void*)p) T(::boost::forward<Args>(args)...); } 282 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 283 public: 284 #define BOOST_PP_LOCAL_MACRO(n) \ 285 template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ 286 static void construct(Alloc &a, T *p \ 287 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 288 { \ 289 ::boost::integral_constant<bool, container_detail::is_std_allocator<Alloc>::value> flag; \ 290 allocator_traits::priv_construct(flag, a, p \ 291 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ 292 } \ 293 // 294 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) 295 #include BOOST_PP_LOCAL_ITERATE() 296 297 private: 298 #define BOOST_PP_LOCAL_MACRO(n) \ 299 template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ 300 static void priv_construct(boost::false_type, Alloc &a, T *p \ 301 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ 302 { \ 303 const bool value = \ 304 boost::container::container_detail::has_member_function_callable_with_construct \ 305 < Alloc, T* BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_FWD_TYPE, _) >::value; \ 306 ::boost::integral_constant<bool, value> flag; \ 307 priv_construct_dispatch2(flag, a, p \ 308 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ 309 } \ 310 \ 311 template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ 312 static void priv_construct(boost::true_type, Alloc &a, T *p \ 313 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ 314 { \ 315 priv_construct_dispatch2(boost::false_type(), a, p \ 316 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ 317 } \ 318 \ 319 template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ 320 static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p \ 321 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ 322 { a.construct( p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); } \ 323 \ 324 template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ 325 static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p \ 326 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \ 327 { ::new((void*)p) T(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ 328 // 329 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) 330 #include BOOST_PP_LOCAL_ITERATE() 331 #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 332 #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 333 334 ///@endcond 335 }; 336 337 } //namespace container { 338 } //namespace boost { 339 340 #include <boost/container/detail/config_end.hpp> 341 342 #endif // ! defined(BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP)
Container-->Concepts-->General concepts-->Container
- A container is an object that stores other objects (its elements), and that has methods for accessing its elements. In particular, every type that is a model of Container has an associated iterator type that can be used to iterate/traverse through the Container’s elements.
- There is no guarantee that the elements of a Container are stored in any definite order; the order might, in fact, be different upon each iteration through the container. Nor is there a guarantee that more than one iterator into a Container may be active at any one time.
- Associated Type (which are defined in Allocator):
- Value type (X:: value_type);
- Iterator type ( X::iterator);
- Const iterator type (X::const_iterator);
- Reference type (X:: reference);
- Const reference type (X::const_reference);
- Pointer type( X:: pointer);
- Distance type( X::difference_type);
- Size type(X::size_type);
- Valid expression: Beginning of range ( a.begin(); End of range ( a.end() ); Size (a.size()); Maximum size ( a.max_size()); Empty container(a.empty()); Swap (a.swap(b));
Container-->Concepts-->General concepts-->Forward Container
- A forward container is a Container whose elements are arranged in a definite order: the ordering will not change spontaneously/naturally/unaffectedly from iteration to iteration. The requirements of a definite ordering allows the definition of element-by-element equality (if the container’s element type is Equality Comparable) and of lexicographical (edited by vocabulary) ordering ( in the container’s element type is LessThan Comparable).
- Complexity Guarantees: The equality and inequality operations are linear in the container’s size.
- Invariants: Two different iterations through a forward container will access its elements in the same order, providing that there have been no intervening mutative operations.
- Must support functions: EqualityComparable, LessThanComparable.
Container-->Concepts-->General concepts-->Reversible Container
- A reversible container is a forward container whose iterators are bidirectional iterators. It allows backwards iteration through the container.
- Two new types are introduced. In addition, the iterator and the const iterator type must satisfy a more stringent/severe/tight/strict requirement than for a Forward Container. The iterator and reverse iterator types must be Bidirectional iterators, not merely Forward Iterators.
- X::reverse_iterator: A Reverse Iterator adaptor whose base iterator type is container’s iterator type. Incrementing an object of type reverse_iterator moved backwards through the container: the Reverse Iterator adaptor maps operator++ to operator--.
- X::const_reverse_iterator: A Reverse Iterator adaptor whose base iterator type is the container’s const iterator type.
- a.rbegin() == X::reverse_iterator (a.end() ); a.rend() == X::reverse_iterator (a.begin() );
Container-->Concepts-->General concepts-->Random Access Container
- A Random Access Container is a Reversible Container whose iterator type is a Random Access Iterator. It provides amortized constant time access to arbitrary elements.
- No additional types beyond those defined in Reversible Container. However, the requirements for the iterator type are strengthened: it must be a Random Access Iterator.
- The element returned by a[n] is the same as the one obtained by incrementing a.begin() n times and then dereferencing the resulting iterator.
Sequences->Sequence Container
- A sequence is a variable-sized Container whose elements are arranged in a strict linear order. It supports insertion and removal of elements.
- Forward Container; Default Constructible
- The fill constructor, default constructor and range constructor are linear
- Front is amortized constant time.
- Fill insert, range insert, and range erase are linear.
- The complexities of single-element insert and erase are sequence dependent.
- Models: vector; deque; list; slist
- Note that p being equal to a.begin() means to insert something at the beginning of a( that is, before any elements already in a), and p being equal to a.end() means to append something to the end of a.
- There is no guarantee that a valid iterator on a is still valid after an insertion or an erasure/removal. In some cases iterators do remain valid, and in other cases they do not. The details are different for each sequence class.
- a.insert(p, n, t) is guaranteed to be no slower than calling a.insert( p, t) n times, In some cases it is significantly faster.
- Vector is usually preferable to deque and list . Deque is useful in the case of frequent insertions ato both the beginning an end of the sequence, and list and slist are useful in the case of frequent insertions in the middle of the sequence. In almost all other situations, vector is more efficient.
Sequences->Front Insertion Sequence
- A Front Insertion Sequence is a Sequence where it is possible to insert an element at the beginning, or to access the first element, in amortized constant time. Front Insertion Sequence have special member functions as a short hand for those operations.
- Front, push front, and pop front are amortized constant time.
- Models: list; deque
- Front is actually defined in Sequence, since it is always possible to implement it in amortized constant time. Its definition is repealed/abolished here, along with push front and pop front, in the interest of clarity.
- This complexity guarantee is the only reason that front(), push_front(), and pop_front are defined : they provided no additional functionality. Not every sequence must define these operations, but it is guaranteed that they are efficient if they exist at all.
Sequences->Back Insertion Sequence
- A Back Insertion Sequence is a Sequence where it is possible to append an element to the end, or to access the last element, in amortized constant time. Back Insertion Sequence have special member functions as a shorthand for those operations.
- Back, push back, and pop back are amortized constant time.
- Models: vector, list, deque
- This complexity guarantee is the only reason that back(), push_back() and pop_back() are defined: they provide no additional functionality. Not every sequence must define these operations, but it is guaranteed that they are efficient if they exist at all.
Associative->Associative Container
- An Associative Container is a variable-sized Container that supports efficient retrieval of elements /values based on keys. It supports insertion and removal / erasure, but differs from a Sequence in that it does not provide a mechanism for inserting an element at specific position.
- As with all containers, the elements in an Associative Container are of type value_type. Additionally, each element in an Associative Container has a key, being of type key_type.
- In some Associative Containers, Simple Associative Containers, the value_type and key_type are the same: elements are their own keys. In others, the key is some specific part of the value. Since elements are stored according to their keys, it is essential that the key associated with each element is immutable.
- In Simple Associative Containers this means that the elements themselves are immutable, while in other types of Associative Containers, such as Pair Associative Containers, the elements themselves are mutable but the part of an element that is its key cannot be modified. This means that an Associative Containers’ value type is not Assignable /Allocative.
- The fact that the value type of an Associative Container is not Assignable has an important consequence: associative containers cannot have mutable iterators. This is simply because a mutable iterator (as defined in the Trivial Iterator requirements) must allow assignment. That is, if I is a mutable iterator and t is an object of I’s value type, then *I = t must be a valid expression.
- In Simple Associative Containers, where the elements are the keys, the elements are completely mutable; the nested /types iterator and const_iterator are therefore the same. Other types of associative containers, however, do have mutable elements, and do provide iterators through which elements can be modified.
- Pair Associative Containers, for example, have two different nested types iterator and const_iterator. Even in this case, iterator is not a mutable iterator: as explained above, it does not provide the expression *I = t. It is, however, possible to modify an element through such an iterator: if, for example, I is of type map<int, double>, then (*i).second = 3 is a valid expression.
- In some associative containers, Unique Associative Containers, it is guaranteed that no two elements have the same key. In other associative containers. Multiple Associative Containers, multiple elements with the same key are permitted.
- Models: set; multiset; hash_set; hash_multiset; map; multimap; hash_map; hash_multimap
- Red-Black Tree:http://en.wikipedia.org/wiki/Red%E2%80%93black_tree
-
1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_CONTAINER_TREE_HPP 12 #define BOOST_CONTAINER_TREE_HPP 13 14 #include "config_begin.hpp" 15 #include <boost/container/detail/workaround.hpp> 16 #include <boost/container/container_fwd.hpp> 17 18 #include <boost/move/utility.hpp> 19 #include <boost/intrusive/pointer_traits.hpp> 20 #include <boost/type_traits/has_trivial_destructor.hpp> 21 #include <boost/detail/no_exceptions_support.hpp> 22 #include <boost/intrusive/rbtree.hpp> 23 24 #include <boost/container/detail/utilities.hpp> 25 #include <boost/container/detail/algorithms.hpp> 26 #include <boost/container/detail/node_alloc_holder.hpp> 27 #include <boost/container/detail/destroyers.hpp> 28 #include <boost/container/detail/pair.hpp> 29 #include <boost/container/detail/type_traits.hpp> 30 #include <boost/container/allocator_traits.hpp> 31 #include <boost/detail/no_exceptions_support.hpp> 32 #ifndef BOOST_CONTAINER_PERFECT_FORWARDING 33 #include <boost/container/detail/preprocessor.hpp> 34 #endif 35 36 #include <utility> //std::pair 37 #include <iterator> 38 #include <algorithm> 39 40 namespace boost { 41 namespace container { 42 namespace container_detail { 43 44 template<class Key, class Value, class KeyCompare, class KeyOfValue> 45 struct tree_value_compare: public KeyCompare 46 { 47 typedef Value value_type; 48 typedef KeyCompare key_compare; 49 typedef KeyOfValue key_of_value; 50 typedef Key key_type; 51 52 tree_value_compare(const key_compare &kcomp) 53 : key_compare(kcomp) 54 {} 55 56 const key_compare &key_comp() const 57 { return static_cast<const key_compare &>(*this); } 58 59 key_compare &key_comp() 60 { return static_cast<key_compare &>(*this); } 61 62 template<class T> 63 struct is_key 64 { 65 static const bool value = is_same<const T, const key_type>::value; 66 }; 67 68 template<class T> 69 typename enable_if_c<is_key<T>::value, const key_type &>::type key_forward(const T &key) const 70 { return key; } 71 72 template<class T> 73 typename enable_if_c<!is_key<T>::value, const key_type &>::type key_forward(const T &key) const 74 { return KeyOfValue()(key); } 75 76 template<class KeyType, class KeyType2> 77 bool operator()(const KeyType &key1, const KeyType2 &key2) const 78 { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } 79 }; 80 81 template<class VoidPointer> 82 struct rbtree_hook 83 { 84 typedef typename container_detail::bi::make_set_base_hook 85 < container_detail::bi::void_pointer<VoidPointer> 86 , container_detail::bi::link_mode<container_detail::bi::normal_link> 87 , container_detail::bi::optimize_size<true> 88 >::type type; 89 }; 90 91 //This trait is used to type-pun std::pair because in C++03 92 //compilers std::pair is useless for C++11 features 93 template<class T> 94 struct rbtree_internal_data_type 95 { 96 typedef T type; 97 }; 98 99 template<class T1, class T2> 100 struct rbtree_internal_data_type< std::pair<T1, T2> > 101 { 102 typedef pair<T1, T2> type; 103 }; 104 //The node to be store in the tree 105 template <class T, class VoidPointer> 106 struct rbtree_node: public rbtree_hook<VoidPointer>::type 107 { 108 private: 109 //BOOST_COPYABLE_AND_MOVABLE(rbtree_node) 110 rbtree_node(); 111 public: 112 typedef typename rbtree_hook<VoidPointer>::type hook_type; 113 typedef T value_type; 114 typedef typename rbtree_internal_data_type<T>::type internal_type; 115 typedef rbtree_node<T, VoidPointer> node_type; 116 T &get_data() 117 { 118 T* ptr = reinterpret_cast<T*>(&this->m_data); 119 return *ptr; 120 } 121 const T &get_data() const 122 { 123 const T* ptr = reinterpret_cast<const T*>(&this->m_data); 124 return *ptr; 125 } 126 internal_type m_data; 127 template<class A, class B> 128 void do_assign(const std::pair<const A, B> &p) 129 { 130 const_cast<A&>(m_data.first) = p.first; 131 m_data.second = p.second; 132 } 133 template<class A, class B> 134 void do_assign(const pair<const A, B> &p) 135 { 136 const_cast<A&>(m_data.first) = p.first; 137 m_data.second = p.second; 138 } 139 template<class V> 140 void do_assign(const V &v) 141 { m_data = v; } 142 143 template<class A, class B> 144 void do_move_assign(std::pair<const A, B> &p) 145 { 146 const_cast<A&>(m_data.first) = ::boost::move(p.first); 147 m_data.second = ::boost::move(p.second); 148 } 149 template<class A, class B> 150 void do_move_assign(pair<const A, B> &p) 151 { 152 const_cast<A&>(m_data.first) = ::boost::move(p.first); 153 m_data.second = ::boost::move(p.second); 154 } 155 template<class V> 156 void do_move_assign(V &v) 157 { m_data = ::boost::move(v); } 158 }; 159 160 }//namespace container_detail { 161 162 namespace container_detail { 163 template<class A, class ValueCompare> 164 struct intrusive_rbtree_type 165 { 166 typedef typename boost::container:: 167 allocator_traits<A>::value_type value_type; 168 typedef typename boost::container:: 169 allocator_traits<A>::void_pointer void_pointer; 170 typedef typename boost::container:: 171 allocator_traits<A>::size_type size_type; 172 typedef typename container_detail::rbtree_node 173 <value_type, void_pointer> node_type; 174 typedef node_compare<ValueCompare, node_type> node_compare_type; 175 typedef typename container_detail::bi::make_rbtree 176 <node_type 177 ,container_detail::bi::compare<node_compare_type> 178 ,container_detail::bi::base_hook<typename rbtree_hook<void_pointer>::type> 179 ,container_detail::bi::constant_time_size<true> 180 ,container_detail::bi::size_type<size_type> 181 >::type container_type; 182 typedef container_type type ; 183 }; 184 } //namespace container_detail { 185 186 namespace container_detail { 187 template <class Key, class Value, class KeyOfValue,class KeyCompare, class A> 188 class rbtree: protected container_detail::node_alloc_holder 189 < A 190 , typename container_detail::intrusive_rbtree_type 191 <A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> 192 >::type 193 , KeyCompare 194 > 195 { 196 typedef typename container_detail::intrusive_rbtree_type 197 < A, tree_value_compare 198 <Key, Value, KeyCompare, KeyOfValue> 199 >::type Icont; 200 typedef container_detail::node_alloc_holder<A, Icont, KeyCompare> AllocHolder; 201 typedef typename AllocHolder::NodePtr NodePtr; 202 typedef rbtree < Key, Value, KeyOfValue, KeyCompare, A> ThisType; 203 typedef typename AllocHolder::NodeAlloc NodeAlloc; 204 typedef typename AllocHolder::ValAlloc ValAlloc; 205 typedef typename AllocHolder::Node Node; 206 typedef typename Icont::iterator iiterator; 207 typedef typename Icont::const_iterator iconst_iterator; 208 typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer; 209 typedef typename AllocHolder::allocator_v1 allocator_v1; 210 typedef typename AllocHolder::allocator_v2 allocator_v2; 211 typedef typename AllocHolder::alloc_version alloc_version; 212 213 class RecyclingCloner; 214 friend class RecyclingCloner; 215 216 class RecyclingCloner 217 { 218 public: 219 RecyclingCloner(AllocHolder &holder, Icont &irbtree) 220 : m_holder(holder), m_icont(irbtree) 221 {} 222 223 NodePtr operator()(const Node &other) const 224 { 225 if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){ 226 //First recycle a node (this can't throw) 227 BOOST_TRY{ 228 //This can throw 229 p->do_assign(other.m_data); 230 return p; 231 } 232 BOOST_CATCH(...){ 233 //If there is an exception destroy the whole source 234 m_holder.destroy_node(p); 235 while((p = m_icont.unlink_leftmost_without_rebalance())){ 236 m_holder.destroy_node(p); 237 } 238 BOOST_RETHROW 239 } 240 BOOST_CATCH_END 241 } 242 else{ 243 return m_holder.create_node(other.m_data); 244 } 245 } 246 247 AllocHolder &m_holder; 248 Icont &m_icont; 249 }; 250 class RecyclingMoveCloner; 251 friend class RecyclingMoveCloner; 252 class RecyclingMoveCloner 253 { 254 public: 255 RecyclingMoveCloner(AllocHolder &holder, Icont &irbtree): m_holder(holder), m_icont(irbtree) 256 {} 257 258 NodePtr operator()(const Node &other) const 259 { 260 if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){ 261 //First recycle a node (this can't throw) 262 BOOST_TRY{ 263 //This can throw 264 p->do_move_assign(const_cast<Node &>(other).m_data); 265 return p; 266 } 267 BOOST_CATCH(...){ 268 //If there is an exception destroy the whole source 269 m_holder.destroy_node(p); 270 while((p = m_icont.unlink_leftmost_without_rebalance())){ 271 m_holder.destroy_node(p); 272 } 273 BOOST_RETHROW 274 } 275 BOOST_CATCH_END 276 } 277 else{ 278 return m_holder.create_node(other.m_data); 279 } 280 } 281 282 AllocHolder &m_holder; 283 Icont &m_icont; 284 }; 285 286 BOOST_COPYABLE_AND_MOVABLE(rbtree) 287 288 public: 289 typedef Key key_type; 290 typedef Value value_type; 291 typedef A allocator_type; 292 typedef KeyCompare key_compare; 293 typedef tree_value_compare< Key, Value, KeyCompare, KeyOfValue> value_compare; 294 typedef typename boost::container::allocator_traits<A>::pointer pointer; 295 typedef typename boost::container::allocator_traits<A>::const_pointer const_pointer; 296 typedef typename boost::container::allocator_traits<A>::reference reference; 297 typedef typename boost::container::allocator_traits<A>::const_reference const_reference; 298 typedef typename boost::container::allocator_traits<A>::size_type size_type; 299 typedef typename boost::container::allocator_traits<A>::difference_type difference_type; 300 typedef difference_type rbtree_difference_type; 301 typedef pointer rbtree_pointer; 302 typedef const_pointer rbtree_const_pointer; 303 typedef reference rbtree_reference; 304 typedef const_reference rbtree_const_reference; 305 typedef NodeAlloc stored_allocator_type; 306 307 private: 308 309 template<class KeyValueCompare> 310 struct key_node_compare: private KeyValueCompare 311 { 312 key_node_compare(const KeyValueCompare &comp) 313 : KeyValueCompare(comp) 314 {} 315 316 template<class T> 317 struct is_node 318 { 319 static const bool value = is_same<T, Node>::value; 320 }; 321 322 template<class T> 323 typename enable_if_c<is_node<T>::value, const value_type &>::type key_forward(const T &node) const 324 { return node.get_data(); } 325 326 template<class T> 327 typename enable_if_c<!is_node<T>::value, const T &>::type key_forward(const T &key) const 328 { return key; } 329 330 template<class KeyType, class KeyType2> 331 bool operator()(const KeyType &key1, const KeyType2 &key2) const 332 { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); } 333 }; 334 335 typedef key_node_compare<value_compare> KeyNodeCompare; 336 337 public: 338 //rbtree const_iterator 339 class const_iterator 340 : public std::iterator 341 < std::bidirectional_iterator_tag 342 , value_type , rbtree_difference_type 343 , rbtree_const_pointer , rbtree_const_reference> 344 { 345 protected: 346 typedef typename Icont::iterator iiterator; 347 iiterator m_it; 348 explicit const_iterator(iiterator it) : m_it(it){} 349 void prot_incr() { ++m_it; } 350 void prot_decr() { --m_it; } 351 private: 352 iiterator get() 353 { return this->m_it; } 354 355 public: 356 friend class rbtree <Key, Value, KeyOfValue, KeyCompare, A>; 357 typedef rbtree_difference_type difference_type; 358 359 //Constructors 360 const_iterator(): m_it() 361 {} 362 363 //Pointer like operators 364 const_reference operator*() const 365 { return m_it->get_data(); } 366 367 const_pointer operator->() const 368 { return const_pointer(&m_it->get_data()); } 369 370 //Increment / Decrement 371 const_iterator& operator++() 372 { prot_incr(); return *this; } 373 374 const_iterator operator++(int) 375 { iiterator tmp = m_it; ++*this; return const_iterator(tmp); } 376 377 const_iterator& operator--() 378 { prot_decr(); return *this; } 379 380 const_iterator operator--(int) 381 { iiterator tmp = m_it; --*this; return const_iterator(tmp); } 382 383 //Comparison operators 384 bool operator== (const const_iterator& r) const 385 { return m_it == r.m_it; } 386 387 bool operator!= (const const_iterator& r) const 388 { return m_it != r.m_it; } 389 }; 390 391 //rbtree iterator 392 class iterator : public const_iterator 393 { 394 private: 395 explicit iterator(iiterator it) 396 : const_iterator(it) 397 {} 398 iiterator get() 399 { return this->m_it; } 400 public: 401 friend class rbtree <Key, Value, KeyOfValue, KeyCompare, A>; 402 typedef rbtree_pointer pointer; 403 typedef rbtree_reference reference; 404 //Constructors 405 iterator(){} 406 //Pointer like operators 407 reference operator*() const { return this->m_it->get_data(); } 408 pointer operator->() const 409 { return boost::intrusive::pointer_traits<pointer>::pointer_to(this->m_it->get_data()); } 410 //Increment / Decrement 411 iterator& operator++(){ this->prot_incr(); return *this; } 412 413 iterator operator++(int){ iiterator tmp = this->m_it; ++*this; return iterator(tmp); } 414 415 iterator& operator--(){ this->prot_decr(); return *this; } 416 417 iterator operator--(int){ iterator tmp = *this; --*this; return tmp; } 418 }; 419 420 typedef std::reverse_iterator<iterator> reverse_iterator; 421 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 422 423 rbtree(): AllocHolder(key_compare()) 424 {} 425 426 rbtree(const key_compare& comp, const allocator_type& a = allocator_type()): AllocHolder(a, comp) 427 {} 428 429 template <class InputIterator> 430 rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, 431 const allocator_type& a 432 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 433 , typename container_detail::enable_if_c 434 < container_detail::is_input_iterator<InputIterator>::value 435 || container_detail::is_same<alloc_version, allocator_v1>::value 436 >::type * = 0 437 #endif 438 ) 439 : AllocHolder(a, comp) 440 { 441 if(unique_insertion){ 442 this->insert_unique(first, last); 443 } 444 else{ 445 this->insert_equal(first, last); 446 } 447 } 448 template <class InputIterator> 449 rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, 450 const allocator_type& a 451 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 452 , typename container_detail::enable_if_c 453 < !(container_detail::is_input_iterator<InputIterator>::value 454 || container_detail::is_same<alloc_version, allocator_v1>::value) 455 >::type * = 0 456 #endif 457 ) 458 : AllocHolder(a, comp) 459 { 460 if(unique_insertion){ 461 this->insert_unique(first, last); 462 } 463 else{ 464 //Optimized allocation and construction 465 this->allocate_many_and_construct 466 (first, std::distance(first, last), insert_equal_end_hint_functor(this->icont())); 467 } 468 } 469 470 template <class InputIterator> 471 rbtree( ordered_range_t, InputIterator first, InputIterator last 472 , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type() 473 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 474 , typename container_detail::enable_if_c 475 < container_detail::is_input_iterator<InputIterator>::value 476 || container_detail::is_same<alloc_version, allocator_v1>::value 477 >::type * = 0 478 #endif 479 ) 480 : AllocHolder(a, comp) 481 { 482 this->insert_equal(first, last); 483 } 484 485 template <class InputIterator> 486 rbtree( ordered_range_t, InputIterator first, InputIterator last 487 , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type() 488 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 489 , typename container_detail::enable_if_c 490 < !(container_detail::is_input_iterator<InputIterator>::value 491 || container_detail::is_same<alloc_version, allocator_v1>::value) 492 >::type * = 0 493 #endif 494 ) 495 : AllocHolder(a, comp) 496 { 497 //Optimized allocation and construction 498 this->allocate_many_and_construct(first, std::distance(first, last), push_back_functor(this->icont())); 499 } 500 501 rbtree(const rbtree& x):AllocHolder(x, x.key_comp()) 502 { 503 this->icont().clone_from(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 504 } 505 506 rbtree(BOOST_RV_REF(rbtree) x):AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.key_comp()) 507 {} 508 509 rbtree(const rbtree& x, const allocator_type &a): AllocHolder(a, x.key_comp()) 510 { 511 this->icont().clone_from(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 512 } 513 514 rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a): AllocHolder(a, x.key_comp()) 515 { 516 if(this->node_alloc() == x.node_alloc()){ 517 this->icont().swap(x.icont()); 518 } 519 else{ 520 this->icont().clone_from 521 (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); 522 } 523 } 524 525 ~rbtree() 526 {} //AllocHolder clears the tree 527 528 rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x) 529 { 530 if (&x != this){ 531 NodeAlloc &this_alloc = this->get_stored_allocator(); 532 const NodeAlloc &x_alloc = x.get_stored_allocator(); 533 container_detail::bool_<allocator_traits<NodeAlloc>:: 534 propagate_on_container_copy_assignment::value> flag; 535 if(flag && this_alloc != x_alloc){ 536 this->clear(); 537 } 538 this->AllocHolder::copy_assign_alloc(x); 539 //Transfer all the nodes to a temporary tree 540 //If anything goes wrong, all the nodes will be destroyed 541 //automatically 542 Icont other_tree(::boost::move(this->icont())); 543 544 //Now recreate the source tree reusing nodes stored by other_tree 545 this->icont().clone_from 546 (x.icont() 547 , RecyclingCloner(*this, other_tree) 548 , Destroyer(this->node_alloc())); 549 550 //If there are remaining nodes, destroy them 551 NodePtr p; 552 while((p = other_tree.unlink_leftmost_without_rebalance())){ 553 AllocHolder::destroy_node(p); 554 } 555 } 556 return *this; 557 } 558 559 rbtree& operator=(BOOST_RV_REF(rbtree) x) 560 { 561 if (&x != this){ 562 NodeAlloc &this_alloc = this->node_alloc(); 563 NodeAlloc &x_alloc = x.node_alloc(); 564 //If allocators are equal we can just swap pointers 565 if(this_alloc == x_alloc){ 566 //Destroy and swap pointers 567 this->clear(); 568 this->icont() = ::boost::move(x.icont()); 569 //Move allocator if needed 570 this->AllocHolder::move_assign_alloc(x); 571 } 572 //If unequal allocators, then do a one by one move 573 else{ 574 //Transfer all the nodes to a temporary tree 575 //If anything goes wrong, all the nodes will be destroyed 576 //automatically 577 Icont other_tree(::boost::move(this->icont())); 578 579 //Now recreate the source tree reusing nodes stored by other_tree 580 this->icont().clone_from 581 (x.icont() 582 , RecyclingMoveCloner(*this, other_tree) 583 , Destroyer(this->node_alloc())); 584 585 //If there are remaining nodes, destroy them 586 NodePtr p; 587 while((p = other_tree.unlink_leftmost_without_rebalance())){ 588 AllocHolder::destroy_node(p); 589 } 590 } 591 } 592 return *this; 593 } 594 595 public: 596 // accessors: 597 value_compare value_comp() const 598 { return this->icont().value_comp().value_comp(); } 599 key_compare key_comp() const 600 { return this->icont().value_comp().value_comp().key_comp(); } 601 allocator_type get_allocator() const 602 { return allocator_type(this->node_alloc()); } 603 const stored_allocator_type &get_stored_allocator() const 604 { return this->node_alloc(); } 605 stored_allocator_type &get_stored_allocator() 606 { return this->node_alloc(); } 607 iterator begin() 608 { return iterator(this->icont().begin()); } 609 const_iterator begin() const 610 { return this->cbegin(); } 611 iterator end() 612 { return iterator(this->icont().end()); } 613 const_iterator end() const 614 { return this->cend(); } 615 reverse_iterator rbegin() 616 { return reverse_iterator(end()); } 617 const_reverse_iterator rbegin() const 618 { return this->crbegin(); } 619 reverse_iterator rend() 620 { return reverse_iterator(begin()); } 621 const_reverse_iterator rend() const 622 { return this->crend(); } 623 const_iterator cbegin() const 624 { return const_iterator(this->non_const_icont().begin()); } 625 const_iterator cend() const 626 { return const_iterator(this->non_const_icont().end()); } 627 const_reverse_iterator crbegin() const 628 { return const_reverse_iterator(cend()); } 629 const_reverse_iterator crend() const 630 { return const_reverse_iterator(cbegin()); } 631 bool empty() const 632 { return !this->size(); } 633 size_type size() const 634 { return this->icont().size(); } 635 size_type max_size() const 636 { return AllocHolder::max_size(); } 637 void swap(ThisType& x) 638 { AllocHolder::swap(x); } 639 640 public: 641 typedef typename Icont::insert_commit_data insert_commit_data; 642 // insert/erase 643 std::pair<iterator,bool> insert_unique_check 644 (const key_type& key, insert_commit_data &data) 645 { 646 std::pair<iiterator, bool> ret = 647 this->icont().insert_unique_check(key, KeyNodeCompare(value_comp()), data); 648 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 649 } 650 std::pair<iterator,bool> insert_unique_check 651 (const_iterator hint, const key_type& key, insert_commit_data &data) 652 { 653 std::pair<iiterator, bool> ret = 654 this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(value_comp()), data); 655 return std::pair<iterator, bool>(iterator(ret.first), ret.second); 656 } 657 iterator insert_unique_commit(const value_type& v, insert_commit_data &data) 658 { 659 NodePtr tmp = AllocHolder::create_node(v); 660 iiterator it(this->icont().insert_unique_commit(*tmp, data)); 661 return iterator(it); 662 } 663 template<class MovableConvertible> 664 iterator insert_unique_commit 665 (BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data) 666 { 667 NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(mv)); 668 iiterator it(this->icont().insert_unique_commit(*tmp, data)); 669 return iterator(it); 670 } 671 std::pair<iterator,bool> insert_unique(const value_type& v) 672 { 673 insert_commit_data data; 674 std::pair<iterator,bool> ret = 675 this->insert_unique_check(KeyOfValue()(v), data); 676 if(!ret.second) 677 return ret; 678 return std::pair<iterator,bool> 679 (this->insert_unique_commit(v, data), true); 680 } 681 template<class MovableConvertible> 682 std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) mv) 683 { 684 insert_commit_data data; 685 std::pair<iterator,bool> ret = 686 this->insert_unique_check(KeyOfValue()(mv), data); 687 if(!ret.second) 688 return ret; 689 return std::pair<iterator,bool> 690 (this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data), true); 691 } 692 private: 693 std::pair<iterator, bool> emplace_unique_impl(NodePtr p) 694 { 695 value_type &v = p->get_data(); 696 insert_commit_data data; 697 scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc()); 698 std::pair<iterator,bool> ret = 699 this->insert_unique_check(KeyOfValue()(v), data); 700 if(!ret.second){ 701 return ret; 702 } 703 //No throw insertion part, release rollback 704 destroy_deallocator.release(); 705 return std::pair<iterator,bool> 706 ( iterator(iiterator(this->icont().insert_unique_commit(*p, data))) 707 , true ); 708 } 709 iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p) 710 { 711 value_type &v = p->get_data(); 712 insert_commit_data data; 713 std::pair<iterator,bool> ret = 714 this->insert_unique_check(hint, KeyOfValue()(v), data); 715 if(!ret.second){ 716 Destroyer(this->node_alloc())(p); 717 return ret.first; 718 } 719 return iterator(iiterator(this->icont().insert_unique_commit(*p, data))); 720 } 721 public: 722 #ifdef BOOST_CONTAINER_PERFECT_FORWARDING 723 template <class... Args> 724 std::pair<iterator, bool> emplace_unique(Args&&... args) 725 { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); } 726 727 template <class... Args> 728 iterator emplace_hint_unique(const_iterator hint, Args&&... args) 729 { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); } 730 731 template <class... Args> 732 iterator emplace_equal(Args&&... args) 733 { 734 NodePtr p(AllocHolder::create_node(boost::forward<Args>(args)...)); 735 return iterator(this->icont().insert_equal(this->icont().end(), *p)); 736 } 737 738 template <class... Args> 739 iterator emplace_hint_equal(const_iterator hint, Args&&... args) 740 { 741 NodePtr p(AllocHolder::create_node(boost::forward<Args>(args)...)); 742 return iterator(this->icont().insert_equal(hint.get(), *p)); 743 } 744 745 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 746 747 #define BOOST_PP_LOCAL_MACRO(n) \ 748 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 749 std::pair<iterator, bool> emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 750 { \ 751 return this->emplace_unique_impl \ 752 (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ 753 } \ 754 \ 755 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 756 iterator emplace_hint_unique(const_iterator hint \ 757 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 758 { \ 759 return this->emplace_unique_hint_impl \ 760 (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ 761 } \ 762 \ 763 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 764 iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 765 { \ 766 NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ 767 return iterator(this->icont().insert_equal(this->icont().end(), *p)); \ 768 } \ 769 \ 770 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 771 iterator emplace_hint_equal(const_iterator hint \ 772 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 773 { \ 774 NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ 775 return iterator(this->icont().insert_equal(hint.get(), *p)); \ 776 } \ 777 //! 778 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) 779 #include BOOST_PP_LOCAL_ITERATE() 780 781 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 782 783 iterator insert_unique(const_iterator hint, const value_type& v) 784 { 785 insert_commit_data data; 786 std::pair<iterator,bool> ret = this->insert_unique_check(hint, KeyOfValue()(v), data); 787 if(!ret.second) 788 return ret.first; 789 return this->insert_unique_commit(v, data); 790 } 791 792 template<class MovableConvertible> 793 iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) 794 { 795 insert_commit_data data; 796 std::pair<iterator,bool> ret = 797 this->insert_unique_check(hint, KeyOfValue()(mv), data); 798 if(!ret.second) 799 return ret.first; 800 return this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data); 801 } 802 803 template <class InputIterator> 804 void insert_unique(InputIterator first, InputIterator last) 805 { 806 if(this->empty()){ 807 //Insert with end hint, to achieve linear 808 //complexity if [first, last) is ordered 809 const_iterator hint(this->cend()); 810 for( ; first != last; ++first) 811 hint = this->insert_unique(hint, *first); 812 } 813 else{ 814 for( ; first != last; ++first) 815 this->insert_unique(*first); 816 } 817 } 818 819 iterator insert_equal(const value_type& v) 820 { 821 NodePtr p(AllocHolder::create_node(v)); 822 return iterator(this->icont().insert_equal(this->icont().end(), *p)); 823 } 824 825 template<class MovableConvertible> 826 iterator insert_equal(BOOST_FWD_REF(MovableConvertible) mv) 827 { 828 NodePtr p(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); 829 return iterator(this->icont().insert_equal(this->icont().end(), *p)); 830 } 831 832 iterator insert_equal(const_iterator hint, const value_type& v) 833 { 834 NodePtr p(AllocHolder::create_node(v)); 835 return iterator(this->icont().insert_equal(hint.get(), *p)); 836 } 837 838 template<class MovableConvertible> 839 iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) 840 { 841 NodePtr p(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); 842 return iterator(this->icont().insert_equal(hint.get(), *p)); 843 } 844 845 template <class InputIterator> 846 void insert_equal(InputIterator first, InputIterator last) 847 { 848 //Insert with end hint, to achieve linear 849 //complexity if [first, last) is ordered 850 const_iterator hint(this->cend()); 851 for( ; first != last; ++first) 852 hint = this->insert_equal(hint, *first); 853 } 854 855 iterator erase(const_iterator position) 856 { return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc()))); } 857 858 size_type erase(const key_type& k) 859 { return AllocHolder::erase_key(k, KeyNodeCompare(value_comp()), alloc_version()); } 860 861 iterator erase(const_iterator first, const_iterator last) 862 { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } 863 864 void clear() 865 { AllocHolder::clear(alloc_version()); } 866 867 // set operations: 868 iterator find(const key_type& k) 869 { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); } 870 871 const_iterator find(const key_type& k) const 872 { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); } 873 874 size_type count(const key_type& k) const 875 { return size_type(this->icont().count(k, KeyNodeCompare(value_comp()))); } 876 877 iterator lower_bound(const key_type& k) 878 { return iterator(this->icont().lower_bound(k, KeyNodeCompare(value_comp()))); } 879 880 const_iterator lower_bound(const key_type& k) const 881 { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(value_comp()))); } 882 883 iterator upper_bound(const key_type& k) 884 { return iterator(this->icont().upper_bound(k, KeyNodeCompare(value_comp()))); } 885 886 const_iterator upper_bound(const key_type& k) const 887 { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); } 888 889 std::pair<iterator,iterator> equal_range(const key_type& k) 890 { 891 std::pair<iiterator, iiterator> ret = 892 this->icont().equal_range(k, KeyNodeCompare(value_comp())); 893 return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second)); 894 } 895 896 std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const 897 { 898 std::pair<iiterator, iiterator> ret = 899 this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp())); 900 return std::pair<const_iterator,const_iterator> 901 (const_iterator(ret.first), const_iterator(ret.second)); 902 } 903 904 private: 905 class insert_equal_end_hint_functor; 906 friend class insert_equal_end_hint_functor; 907 class insert_equal_end_hint_functor 908 { 909 Icont &icont_; 910 const iconst_iterator cend_; 911 912 public: 913 insert_equal_end_hint_functor(Icont &icont) 914 : icont_(icont), cend_(this->icont_.cend()) 915 {} 916 917 void operator()(Node &n) 918 { this->icont_.insert_equal(cend_, n); } 919 }; 920 921 class push_back_functor; 922 friend class push_back_functor; 923 924 class push_back_functor 925 { 926 Icont &icont_; 927 928 public: 929 push_back_functor(Icont &icont) 930 : icont_(icont) 931 {} 932 933 void operator()(Node &n) 934 { this->icont_.push_back(n); } 935 }; 936 }; 937 938 template <class Key, class Value, class KeyOfValue, 939 class KeyCompare, class A> 940 inline bool operator==(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 941 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 942 { 943 return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); 944 } 945 946 template <class Key, class Value, class KeyOfValue, 947 class KeyCompare, class A> 948 inline bool operator<(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 949 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 950 { 951 return std::lexicographical_compare(x.begin(), x.end(), 952 y.begin(), y.end()); 953 } 954 955 template <class Key, class Value, class KeyOfValue, 956 class KeyCompare, class A> 957 inline bool operator!=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 958 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 959 { 960 return !(x == y); 961 } 962 963 template <class Key, class Value, class KeyOfValue, 964 class KeyCompare, class A> 965 inline bool operator>(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 966 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 967 { 968 return y < x; 969 } 970 971 template <class Key, class Value, class KeyOfValue, 972 class KeyCompare, class A> 973 inline bool operator<=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 974 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 975 { 976 return !(y < x); 977 } 978 979 template <class Key, class Value, class KeyOfValue, 980 class KeyCompare, class A> 981 inline bool operator>=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 982 const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 983 { 984 return !(x < y); 985 } 986 987 988 template <class Key, class Value, class KeyOfValue, 989 class KeyCompare, class A> 990 inline void swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x, 991 rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) 992 { 993 x.swap(y); 994 } 995 996 } //namespace container_detail { 997 } //namespace container { 998 /* 999 //!has_trivial_destructor_after_move<> == true_type 1000 //!specialization for optimizations 1001 template <class K, class V, class KOV, 1002 class C, class A> 1003 struct has_trivial_destructor_after_move 1004 <boost::container::container_detail::rbtree<K, V, KOV, C, A> > 1005 { 1006 static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value; 1007 }; 1008 */ 1009 } //namespace boost { 1010 1011 #include <boost/container/detail/config_end.hpp> 1012 1013 #endif //BOOST_CONTAINER_TREE_HPP
二叉树的意思是:任何节点最多只能有两个子节点的树。二叉搜索树可提供log(N)的元素插入和访问,它的节点旋转规则是:任何节点的键值一定大于其左子节点树中的每个节点的键值,并小于其右子树中的每个节点的键值。因此,从树节点一直往左走到底,即得最小元素;从根节点一直往右走到底,却得最大元素。但是,由于插入值无规律,二叉搜索树可能失去平衡,造成搜索效率低落的情况。解决办法就是尽量使树形左右“平衡”,对于何为“平衡”,没有一个绝对的定义,大致的意思就是“没有一个节点过深”。常见的平衡二叉树有AVL-tree, RB-tree, AA-tree,它们都比上面说的一般二叉树复杂,插入节点和删除节点时要做一些额外操作来维护树形平衡,但是它们可以避免极难应付的极不平衡的情况,而且由于它们总是保持某种程度的平衡,所以元素访问时间平均而言就比较少。
SGI STL实现的搜索树是RB-tree,它在一般二叉树的基础上增加了以下必须满足的条件:
- 每个节点不是红色就是黑色;
- 根节点为黑色;
- 如果节点为红,其子节点必须为黑,如果节点为黑,则随意;
- 任一节点到树尾端的任何路径(比如从根节点到任意一个叶节点),所含的黑节点数量必须相同。
根据规则4,新增节点必须为红色;根据规则3,新增节点的父节点必须为黑。当新节点根据一般二叉树搜索规则到达其插入点,却未能符合上述条件时,就必须调整节点颜色和旋转树形。注意经过调整后,叶节点可能为黑色。
Associative Container->Simple Associative Container
- A simple Associative Container is an Associative Container where elements are their own keys. A key in a Simple Associative Container is not associated with any additional value.
- Immutability of element: Every element of a Simple Associative Container is immutable. Objects may be inserted and erased, but not modified.
- Models: set; multiset; hash_set; hash_multiset;
- This is a consequence of the Immutability of Keys invariant of Associative Container. Keys may never be modified; values in a Simple Associative Container are themselves keys, so it immediately follows that values in a Simple Associative Container may not be modified.
- template <class _Key, class _Value, class _KeyOfValue, class _Compare, class _Alloc = _BP_STL_DEFAULT_ALLOCATOR(_Value) >76. class _Rb_tree : protected _Rb_tree_base<_Value, _Alloc>
- With concept of composition, template class _Rb_tree is regarded as a type of a member within template class set or hash_set and so on.
-
1 //! A set is a kind of associative container that supports unique keys (contains at 2 //! most one of each key value) and provides for fast retrieval of the keys themselves. 3 //! Class set supports bidirectional iterators. 4 //! A set satisfies all of the requirements of a container and of a reversible container,and of an associative container. A set also provides most operations described in 5 //! for unique keys. 6 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED 7 template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> > 8 #else 9 template <class Key, class Compare, class Allocator> 10 #endif 11 class set 12 { 13 private: 14 BOOST_COPYABLE_AND_MOVABLE(set) 15 typedef container_detail::rbtree<Key, Key, 16 container_detail::identity<Key>, Compare, Allocator> tree_t; 17 tree_t m_tree; // red-black tree representing set 18 public: 19 typedef Key key_type; 20 typedef Key value_type; 21 typedef Compare key_compare; 22 typedef Compare value_compare; 23 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; 24 typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer; 25 typedef typename ::boost::container::allocator_traits<Allocator>::reference reference; 26 typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference; 27 typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type; 28 typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type; 29 typedef Allocator allocator_type; 30 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type; 31 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::iterator) iterator; 32 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_iterator) const_iterator; 33 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::reverse_iterator) reverse_iterator; 34 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_reverse_iterator) const_reverse_iterator; 35 set(): m_tree(){} 36 explicit set(const Compare& comp,const allocator_type& a = allocator_type()): m_tree(comp, a){} 37 38 template <class InputIterator> 39 set(InputIterator first, InputIterator last, const Compare& comp = Compare(), 40 const allocator_type& a = allocator_type()): m_tree(true, first, last, comp, a) 41 {} 42 template <class InputIterator> 43 set( ordered_unique_range_t, InputIterator first, InputIterator last 44 , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) 45 : m_tree(ordered_range, first, last, comp, a) 46 {} 47 set(const set& x): m_tree(x.m_tree) 48 {} 49 set(BOOST_RV_REF(set) x): m_tree(boost::move(x.m_tree)) 50 {} 51 set(const set& x, const allocator_type &a): m_tree(x.m_tree, a) 52 {} 53 set(BOOST_RV_REF(set) x, const allocator_type &a): m_tree(boost::move(x.m_tree), a) 54 {} 55 set& operator=(BOOST_COPY_ASSIGN_REF(set) x) 56 { 57 m_tree = x.m_tree; return *this; 58 } 59 set& operator=(BOOST_RV_REF(set) x) 60 { 61 m_tree = boost::move(x.m_tree); return *this; 62 } 63 allocator_type get_allocator() const 64 { 65 return m_tree.get_allocator(); 66 } 67 const stored_allocator_type &get_stored_allocator() const 68 { 69 return m_tree.get_stored_allocator(); 70 } 71 stored_allocator_type &get_stored_allocator() 72 { return m_tree.get_stored_allocator(); } 73 74 iterator begin() 75 { return m_tree.begin(); } 76 77 const_iterator begin() const 78 { return m_tree.begin(); } 79 80 iterator end() 81 { return m_tree.end(); } 82 83 const_iterator end() const 84 { return m_tree.end(); } 85 86 reverse_iterator rbegin() 87 { return m_tree.rbegin(); } 88 89 const_reverse_iterator rbegin() const 90 { return m_tree.rbegin(); } 91 92 reverse_iterator rend() 93 { return m_tree.rend(); } 94 95 const_reverse_iterator rend() const 96 { return m_tree.rend(); } 97 98 const_iterator cbegin() const 99 { return m_tree.cbegin(); } 100 101 const_iterator cend() const 102 { return m_tree.cend(); } 103 104 const_reverse_iterator crbegin() const 105 { return m_tree.crbegin(); } 106 107 const_reverse_iterator crend() const 108 { return m_tree.crend(); } 109 110 bool empty() const 111 { return m_tree.empty(); } 112 113 size_type size() const 114 { return m_tree.size(); } 115 116 size_type max_size() const 117 { return m_tree.max_size(); } 118 119 #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 120 121 template <class... Args> 122 std::pair<iterator,bool> emplace(Args&&... args) 123 { return m_tree.emplace_unique(boost::forward<Args>(args)...); } 124 125 template <class... Args> 126 iterator emplace_hint(const_iterator hint, Args&&... args) 127 { return m_tree.emplace_hint_unique(hint, boost::forward<Args>(args)...); } 128 129 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 130 131 #define BOOST_PP_LOCAL_MACRO(n) \ 132 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 133 std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 134 { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ 135 \ 136 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 137 iterator emplace_hint(const_iterator hint \ 138 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 139 { return m_tree.emplace_hint_unique(hint \ 140 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \ 141 //! 142 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) 143 #include BOOST_PP_LOCAL_ITERATE() 144 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 145 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 146 147 std::pair<iterator, bool> insert(const value_type &x); 148 149 std::pair<iterator, bool> insert(value_type &&x); 150 #else 151 private: 152 typedef std::pair<iterator, bool> insert_return_pair; 153 public: 154 BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->priv_insert) 155 #endif 156 157 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 158 iterator insert(const_iterator p, const value_type &x); 159 iterator insert(const_iterator position, value_type &&x); 160 #else 161 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator) 162 #endif 163 164 template <class InputIterator> 165 void insert(InputIterator first, InputIterator last) 166 { m_tree.insert_unique(first, last); } 167 168 iterator erase(const_iterator p) 169 { return m_tree.erase(p); } 170 171 size_type erase(const key_type& x) 172 { return m_tree.erase(x); } 173 174 iterator erase(const_iterator first, const_iterator last) 175 { return m_tree.erase(first, last); } 176 177 void swap(set& x) 178 { m_tree.swap(x.m_tree); } 179 180 void clear() 181 { m_tree.clear(); } 182 183 key_compare key_comp() const 184 { return m_tree.key_comp(); } 185 186 value_compare value_comp() const 187 { return m_tree.key_comp(); } 188 189 iterator find(const key_type& x) 190 { return m_tree.find(x); } 191 192 const_iterator find(const key_type& x) const 193 { return m_tree.find(x); } 194 195 size_type count(const key_type& x) const 196 { return m_tree.find(x) == m_tree.end() ? 0 : 1; } 197 198 iterator lower_bound(const key_type& x) 199 { return m_tree.lower_bound(x); } 200 201 const_iterator lower_bound(const key_type& x) const 202 { return m_tree.lower_bound(x); } 203 204 iterator upper_bound(const key_type& x) 205 { return m_tree.upper_bound(x); } 206 207 const_iterator upper_bound(const key_type& x) const 208 { return m_tree.upper_bound(x); } 209 210 std::pair<iterator,iterator> equal_range(const key_type& x) 211 { return m_tree.equal_range(x); } 212 213 std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const 214 { return m_tree.equal_range(x); } 215 216 /// @cond 217 template <class K1, class C1, class A1> 218 friend bool operator== (const set<K1,C1,A1>&, const set<K1,C1,A1>&); 219 220 template <class K1, class C1, class A1> 221 friend bool operator< (const set<K1,C1,A1>&, const set<K1,C1,A1>&); 222 223 private: 224 template <class KeyType> 225 std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x) 226 { return m_tree.insert_unique(::boost::forward<KeyType>(x)); } 227 228 template <class KeyType> 229 iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) 230 { return m_tree.insert_unique(p, ::boost::forward<KeyType>(x)); } 231 /// @endcond 232 }; 233 template <class Key, class Compare, class Allocator> 234 inline bool operator==(const set<Key,Compare,Allocator>& x,const set<Key,Compare,Allocator>& y) 235 { return x.m_tree == y.m_tree; } 236 template <class Key, class Compare, class Allocator> 237 inline bool operator<(const set<Key,Compare,Allocator>& x,const set<Key,Compare,Allocator>& y) 238 { return x.m_tree < y.m_tree; } 239 template <class Key, class Compare, class Allocator> 240 inline bool operator!=(const set<Key,Compare,Allocator>& x,const set<Key,Compare,Allocator>& y) 241 { return !(x == y); } 242 template <class Key, class Compare, class Allocator> 243 inline bool operator>(const set<Key,Compare,Allocator>& x,const set<Key,Compare,Allocator>& y) 244 { return y < x; } 245 template <class Key, class Compare, class Allocator> 246 inline bool operator<=(const set<Key,Compare,Allocator>& x,const set<Key,Compare,Allocator>& y) 247 { return !(y < x); } 248 template <class Key, class Compare, class Allocator> 249 inline bool operator>=(const set<Key,Compare,Allocator>& x,const set<Key,Compare,Allocator>& y) 250 { return !(x < y); } 251 template <class Key, class Compare, class Allocator> 252 inline void swap(set<Key,Compare,Allocator>& x, set<Key,Compare,Allocator>& y) 253 { x.swap(y); } 254 /// @cond 255 256 } 257 template <class Key, class C, class Allocator> 258 struct has_trivial_destructor_after_move<boost::container::set<Key, C, Allocator> > 259 { 260 static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; 261 };
1 //! A multiset is a kind of associative container that supports equivalent keys 2 //! (possibly contains multiple copies of the same key value) and provides for 3 //! fast retrieval of the keys themselves. Class multiset supports bidirectional iterators. 4 //! 5 //! A multiset satisfies all of the requirements of a container and of a reversible 6 //! container, and of an associative container). multiset also provides most operations 7 //! described for duplicate keys. 8 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED 9 template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> > 10 #else 11 template <class Key, class Compare, class Allocator> 12 #endif 13 class multiset 14 { 15 private: 16 BOOST_COPYABLE_AND_MOVABLE(multiset) 17 typedef container_detail::rbtree<Key, Key, 18 container_detail::identity<Key>, Compare, Allocator> tree_t; 19 tree_t m_tree; // red-black tree representing multiset 20 21 public: 22 23 typedef Key key_type; 24 typedef Key value_type; 25 typedef Compare key_compare; 26 typedef Compare value_compare; 27 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; 28 typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer const_pointer; 29 typedef typename ::boost::container::allocator_traits<Allocator>::reference reference; 30 typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference; 31 typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type; 32 typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type; 33 typedef Allocator allocator_type; 34 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type; 35 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::iterator) iterator; 36 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_iterator) const_iterator; 37 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::reverse_iterator) reverse_iterator; 38 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_reverse_iterator) const_reverse_iterator; 39 40 41 multiset(): m_tree() 42 {} 43 44 explicit multiset(const Compare& comp, 45 const allocator_type& a = allocator_type()) 46 : m_tree(comp, a) 47 {} 48 49 template <class InputIterator> 50 multiset(InputIterator first, InputIterator last, 51 const Compare& comp = Compare(), 52 const allocator_type& a = allocator_type()) 53 : m_tree(false, first, last, comp, a) 54 {} 55 56 template <class InputIterator> 57 multiset( ordered_range_t, InputIterator first, InputIterator last 58 , const Compare& comp = Compare() 59 , const allocator_type& a = allocator_type()) 60 : m_tree(ordered_range, first, last, comp, a) 61 {} 62 63 multiset(const multiset& x) 64 : m_tree(x.m_tree) 65 {} 66 67 multiset(BOOST_RV_REF(multiset) x) 68 : m_tree(boost::move(x.m_tree)) 69 {} 70 71 multiset(const multiset& x, const allocator_type &a) 72 : m_tree(x.m_tree, a) 73 {} 74 75 multiset(BOOST_RV_REF(multiset) x, const allocator_type &a) 76 : m_tree(boost::move(x.m_tree), a) 77 {} 78 79 80 multiset& operator=(BOOST_COPY_ASSIGN_REF(multiset) x) 81 { m_tree = x.m_tree; return *this; } 82 83 multiset& operator=(BOOST_RV_REF(multiset) x) 84 { m_tree = boost::move(x.m_tree); return *this; } 85 86 allocator_type get_allocator() const 87 { return m_tree.get_allocator(); } 88 89 stored_allocator_type &get_stored_allocator() 90 { return m_tree.get_stored_allocator(); } 91 92 const stored_allocator_type &get_stored_allocator() const 93 { return m_tree.get_stored_allocator(); } 94 95 iterator begin() 96 { return m_tree.begin(); } 97 98 const_iterator begin() const 99 { return m_tree.begin(); } 100 101 iterator end() 102 { return m_tree.end(); } 103 104 const_iterator end() const 105 { return m_tree.end(); } 106 107 reverse_iterator rbegin() 108 { return m_tree.rbegin(); } 109 110 const_reverse_iterator rbegin() const 111 { return m_tree.rbegin(); } 112 113 reverse_iterator rend() 114 { return m_tree.rend(); } 115 116 const_reverse_iterator rend() const 117 { return m_tree.rend(); } 118 119 const_iterator cbegin() const 120 { return m_tree.cbegin(); } 121 122 const_iterator cend() const 123 { return m_tree.cend(); } 124 125 const_reverse_iterator crbegin() const 126 { return m_tree.crbegin(); } 127 128 const_reverse_iterator crend() const 129 { return m_tree.crend(); } 130 131 bool empty() const 132 { return m_tree.empty(); } 133 134 size_type size() const 135 { return m_tree.size(); } 136 137 size_type max_size() const 138 { return m_tree.max_size(); } 139 140 #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 141 142 template <class... Args> 143 iterator emplace(Args&&... args) 144 { return m_tree.emplace_equal(boost::forward<Args>(args)...); } 145 146 template <class... Args> 147 iterator emplace_hint(const_iterator hint, Args&&... args) 148 { return m_tree.emplace_hint_equal(hint, boost::forward<Args>(args)...); } 149 150 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 151 152 #define BOOST_PP_LOCAL_MACRO(n) \ 153 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 154 iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 155 { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ 156 \ 157 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 158 iterator emplace_hint(const_iterator hint \ 159 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 160 { return m_tree.emplace_hint_equal(hint \ 161 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \ 162 //! 163 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) 164 #include BOOST_PP_LOCAL_ITERATE() 165 166 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 167 168 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 169 170 iterator insert(const value_type &x); 171 iterator insert(value_type &&x); 172 #else 173 BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->priv_insert) 174 #endif 175 176 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 177 178 iterator insert(const_iterator p, const value_type &x); 179 180 iterator insert(const_iterator position, value_type &&x); 181 #else 182 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator) 183 #endif 184 185 template <class InputIterator> 186 void insert(InputIterator first, InputIterator last) 187 { m_tree.insert_equal(first, last); } 188 189 iterator erase(const_iterator p) 190 { return m_tree.erase(p); } 191 192 size_type erase(const key_type& x) 193 { return m_tree.erase(x); } 194 195 iterator erase(const_iterator first, const_iterator last) 196 { return m_tree.erase(first, last); } 197 198 void swap(multiset& x) 199 { m_tree.swap(x.m_tree); } 200 201 void clear() 202 { m_tree.clear(); } 203 204 key_compare key_comp() const 205 { return m_tree.key_comp(); } 206 207 value_compare value_comp() const 208 { return m_tree.key_comp(); } 209 210 iterator find(const key_type& x) 211 { return m_tree.find(x); } 212 213 const_iterator find(const key_type& x) const 214 { return m_tree.find(x); } 215 216 size_type count(const key_type& x) const 217 { return m_tree.count(x); } 218 219 iterator lower_bound(const key_type& x) 220 { return m_tree.lower_bound(x); } 221 222 const_iterator lower_bound(const key_type& x) const 223 { return m_tree.lower_bound(x); } 224 225 iterator upper_bound(const key_type& x) 226 { return m_tree.upper_bound(x); } 227 228 const_iterator upper_bound(const key_type& x) const 229 { return m_tree.upper_bound(x); } 230 231 std::pair<iterator,iterator> equal_range(const key_type& x) 232 { return m_tree.equal_range(x); } 233 234 std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const 235 { return m_tree.equal_range(x); } 236 237 /// @cond 238 template <class K1, class C1, class A1> 239 friend bool operator== (const multiset<K1,C1,A1>&, 240 const multiset<K1,C1,A1>&); 241 template <class K1, class C1, class A1> 242 friend bool operator< (const multiset<K1,C1,A1>&, 243 const multiset<K1,C1,A1>&); 244 private: 245 template <class KeyType> 246 iterator priv_insert(BOOST_FWD_REF(KeyType) x) 247 { return m_tree.insert_equal(::boost::forward<KeyType>(x)); } 248 249 template <class KeyType> 250 iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) 251 { return m_tree.insert_equal(p, ::boost::forward<KeyType>(x)); } 252 253 /// @endcond 254 }; 255 256 template <class Key, class Compare, class Allocator> 257 inline bool operator==(const multiset<Key,Compare,Allocator>& x, 258 const multiset<Key,Compare,Allocator>& y) 259 { return x.m_tree == y.m_tree; } 260 261 template <class Key, class Compare, class Allocator> 262 inline bool operator<(const multiset<Key,Compare,Allocator>& x, 263 const multiset<Key,Compare,Allocator>& y) 264 { return x.m_tree < y.m_tree; } 265 266 template <class Key, class Compare, class Allocator> 267 inline bool operator!=(const multiset<Key,Compare,Allocator>& x, 268 const multiset<Key,Compare,Allocator>& y) 269 { return !(x == y); } 270 271 template <class Key, class Compare, class Allocator> 272 inline bool operator>(const multiset<Key,Compare,Allocator>& x, 273 const multiset<Key,Compare,Allocator>& y) 274 { return y < x; } 275 276 template <class Key, class Compare, class Allocator> 277 inline bool operator<=(const multiset<Key,Compare,Allocator>& x, 278 const multiset<Key,Compare,Allocator>& y) 279 { return !(y < x); } 280 281 template <class Key, class Compare, class Allocator> 282 inline bool operator>=(const multiset<Key,Compare,Allocator>& x,const multiset<Key,Compare,Allocator>& y) 283 { return !(x < y); } 284 285 template <class Key, class Compare, class Allocator> 286 inline void swap(multiset<Key,Compare,Allocator>& x, multiset<Key,Compare,Allocator>& y) 287 { x.swap(y); } 288 289 /// @cond 290 291 }
Associative Container->Pair Associative Container
1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2005-2012. 4 // 5 // Distributed under the Boost Software License, Version 1.0. 6 // (See accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // See http://www.boost.org/libs/container for documentation. 10 // 11 ////////////////////////////////////////////////////////////////////////////// 12 #ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP 13 #define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP 14 #if (defined _MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif 17 #include "config_begin.hpp" 18 #include <boost/container/detail/workaround.hpp> 19 #include <boost/container/detail/mpl.hpp> 20 #include <boost/container/detail/type_traits.hpp> 21 #include <boost/container/detail/mpl.hpp> 22 #include <boost/container/detail/type_traits.hpp> 23 #include <utility> //std::pair 24 #include <algorithm> //std::swap 25 #include <boost/move/utility.hpp> 26 #include <boost/type_traits/is_class.hpp> 27 #ifndef BOOST_CONTAINER_PERFECT_FORWARDING 28 #include <boost/container/detail/preprocessor.hpp> 29 #endif 30 31 namespace boost { 32 namespace container { 33 namespace container_detail { 34 35 template <class T1, class T2> 36 struct pair; 37 template <class T> 38 struct is_pair 39 { 40 static const bool value = false; 41 }; 42 43 template <class T1, class T2> 44 struct is_pair< pair<T1, T2> > 45 { 46 static const bool value = true; 47 }; 48 49 template <class T1, class T2> 50 struct is_pair< std::pair<T1, T2> > 51 { 52 static const bool value = true; 53 }; 54 55 struct pair_nat; 56 struct piecewise_construct_t { }; 57 static const piecewise_construct_t piecewise_construct = piecewise_construct_t(); 58 59 template <class T1, class T2> 60 struct pair 61 { 62 private: 63 BOOST_COPYABLE_AND_MOVABLE(pair) 64 65 public: 66 typedef T1 first_type; 67 typedef T2 second_type; 68 69 T1 first; 70 T2 second; 71 72 //Default constructor 73 pair(): first(), second() 74 {} 75 76 //pair copy assignment 77 pair(const pair& x): first(x.first), second(x.second) 78 {} 79 80 //pair move constructor 81 pair(BOOST_RV_REF(pair) p): first(::boost::move(p.first)), second(::boost::move(p.second)) 82 {} 83 84 template <class D, class S> 85 pair(const pair<D, S> &p): first(p.first), second(p.second) 86 {} 87 88 template <class D, class S> 89 pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p): first(::boost::move(p.first)), second(::boost::move(p.second)) 90 {} 91 92 //pair from two values 93 pair(const T1 &t1, const T2 &t2): first(t1), second(t2) 94 {} 95 96 template<class U, class V> 97 pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v): first(::boost::forward<U>(u)), second(::boost::forward<V>(v)) 98 {} 99 100 //And now compatibility with std::pair 101 pair(const std::pair<T1, T2>& x): first(x.first), second(x.second) 102 {} 103 104 template <class D, class S> 105 pair(const std::pair<D, S>& p): first(p.first), second(p.second) 106 {} 107 108 pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p): first(::boost::move(p.first)), second(::boost::move(p.second)) 109 {} 110 111 template <class D, class S> 112 pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p): first(::boost::move(p.first)), second(::boost::move(p.second)) 113 {} 114 115 //piecewise_construct missing 116 //template <class U, class V> pair(pair<U, V>&& p); 117 //template <class... Args1, class... Args2> 118 // pair(piecewise_construct_t, tuple<Args1...> first_args, 119 // tuple<Args2...> second_args); 120 121 //pair copy assignment 122 pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p) 123 { 124 first = p.first; 125 second = p.second; 126 return *this; 127 } 128 129 //pair move assignment 130 pair& operator=(BOOST_RV_REF(pair) p) 131 { 132 first = ::boost::move(p.first); 133 second = ::boost::move(p.second); 134 return *this; 135 } 136 137 template <class D, class S> 138 typename ::boost::container::container_detail::enable_if_c 139 < !(::boost::container::container_detail::is_same<T1, D>::value && 140 ::boost::container::container_detail::is_same<T2, S>::value) 141 , pair &>::type operator=(const pair<D, S>&p) 142 { 143 first = p.first; 144 second = p.second; 145 return *this; 146 } 147 template <class D, class S> 148 typename ::boost::container::container_detail::enable_if_c 149 < !(::boost::container::container_detail::is_same<T1, D>::value && 150 ::boost::container::container_detail::is_same<T2, S>::value) 151 , pair &>::type operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p) 152 { 153 first = ::boost::move(p.first); 154 second = ::boost::move(p.second); 155 return *this; 156 } 157 //std::pair copy assignment 158 pair& operator=(const std::pair<T1, T2> &p) 159 { 160 first = p.first; 161 second = p.second; 162 return *this; 163 } 164 template <class D, class S> 165 pair& operator=(const std::pair<D, S> &p) 166 { 167 first = ::boost::move(p.first); 168 second = ::boost::move(p.second); 169 return *this; 170 } 171 //std::pair move assignment 172 pair& operator=(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p) 173 { 174 first = ::boost::move(p.first); 175 second = ::boost::move(p.second); 176 return *this; 177 } 178 template <class D, class S> 179 pair& operator=(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p) 180 { 181 first = ::boost::move(p.first); 182 second = ::boost::move(p.second); 183 return *this; 184 } 185 //swap 186 void swap(pair& p) 187 { 188 using std::swap; 189 swap(this->first, p.first); 190 swap(this->second, p.second); 191 } 192 }; 193 194 template <class T1, class T2> 195 inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y) 196 { return static_cast<bool>(x.first == y.first && x.second == y.second); } 197 198 template <class T1, class T2> 199 inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y) 200 { return static_cast<bool>(x.first < y.first || (!(y.first < x.first) && x.second < y.second)); } 201 202 template <class T1, class T2> 203 inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y) 204 { return static_cast<bool>(!(x == y)); } 205 206 template <class T1, class T2> 207 inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y) 208 { return y < x; } 209 210 template <class T1, class T2> 211 inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y) 212 { return static_cast<bool>(!(x < y)); } 213 214 template <class T1, class T2> 215 inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y) 216 { return static_cast<bool>(!(y < x)); } 217 218 template <class T1, class T2> 219 inline pair<T1, T2> make_pair(T1 x, T2 y) 220 { return pair<T1, T2>(x, y); } 221 222 template <class T1, class T2> 223 inline void swap(pair<T1, T2>& x, pair<T1, T2>& y) 224 { 225 swap(x.first, y.first); 226 swap(x.second, y.second); 227 } 228 } //namespace container_detail { 229 } //namespace container { 230 231 //Without this specialization recursive flat_(multi)map instantiation fails 232 //because is_enum needs to instantiate the recursive pair, leading to a compilation error). 233 //This breaks the cycle clearly stating that pair is not an enum avoiding any instantiation. 234 template<class T> 235 struct is_enum; 236 template<class T, class U> 237 struct is_enum< ::boost::container::container_detail::pair<T, U> > 238 { 239 static const bool value = false; 240 }; 241 //This specialization is needed to avoid instantiation of pair in 242 //is_class, and allow recursive maps. 243 template <class T1, class T2> 244 struct is_class< ::boost::container::container_detail::pair<T1, T2> >: public ::boost::true_type 245 {}; 246 247 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES 248 249 template<class T1, class T2> 250 struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> > 251 : ::boost::true_type 252 {}; 253 254 #endif 255 256 257 } //namespace boost { 258 259 #include <boost/container/detail/config_end.hpp> 260 261 #endif //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP
1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_CONTAINER_MAP_HPP 12 #define BOOST_CONTAINER_MAP_HPP 13 14 #if (defined _MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif 17 18 #include <boost/container/detail/config_begin.hpp> 19 #include <boost/container/detail/workaround.hpp> 20 #include <boost/container/container_fwd.hpp> 21 #include <utility> 22 #include <functional> 23 #include <memory> 24 #include <boost/container/detail/tree.hpp> 25 #include <boost/container/detail/value_init.hpp> 26 #include <boost/type_traits/has_trivial_destructor.hpp> 27 #include <boost/container/detail/mpl.hpp> 28 #include <boost/container/detail/utilities.hpp> 29 #include <boost/container/detail/pair.hpp> 30 #include <boost/container/detail/type_traits.hpp> 31 #include <boost/container/throw_exception.hpp> 32 #include <boost/move/utility.hpp> 33 #include <boost/move/detail/move_helpers.hpp> 34 #include <boost/static_assert.hpp> 35 #include <boost/container/detail/value_init.hpp> 36 #include <boost/detail/no_exceptions_support.hpp> 37 38 namespace boost { 39 namespace container { 40 41 /// @cond 42 // Forward declarations of operators == and <, needed for friend declarations. 43 template <class Key, class T, class Compare, class Allocator> 44 inline bool operator==(const map<Key,T,Compare,Allocator>& x, 45 const map<Key,T,Compare,Allocator>& y); 46 47 template <class Key, class T, class Compare, class Allocator> 48 inline bool operator<(const map<Key,T,Compare,Allocator>& x, 49 const map<Key,T,Compare,Allocator>& y); 50 51 //! A map is a kind of associative container that supports unique keys (contains at 52 //! most one of each key value) and provides for fast retrieval of values of another 53 //! type T based on the keys. The map class supports bidirectional iterators. 54 //! A map satisfies all of the requirements of a container and of a reversible 55 //! container and of an associative container. For a 56 //! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>. 57 //! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). 58 //! Allocator is the allocator to allocate the value_types 59 //! (e.g. <i>allocator< std::pair<const Key, T> > </i>). 60 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED 61 template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > > 62 #else 63 template <class Key, class T, class Compare, class Allocator> 64 #endif 65 class map 66 { 67 /// @cond 68 private: 69 BOOST_COPYABLE_AND_MOVABLE(map) 70 71 typedef std::pair<const Key, T> value_type_impl; 72 typedef container_detail::rbtree 73 <Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator> tree_t; 74 typedef container_detail::pair <Key, T> movable_value_type_impl; 75 typedef container_detail::tree_value_compare 76 < Key, value_type_impl, Compare, container_detail::select1st<value_type_impl> 77 > value_compare_impl; 78 tree_t m_tree; // red-black tree representing map 79 /// @endcond 80 81 public: 82 typedef Key key_type; 83 typedef T mapped_type; 84 typedef std::pair<const Key, T> value_type; 85 typedef typename boost::container::allocator_traits<Allocator>::pointer pointer; 86 typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer; 87 typedef typename boost::container::allocator_traits<Allocator>::reference reference; 88 typedef typename boost::container::allocator_traits<Allocator>::const_reference const_reference; 89 typedef typename boost::container::allocator_traits<Allocator>::size_type size_type; 90 typedef typename boost::container::allocator_traits<Allocator>::difference_type difference_type; 91 typedef Allocator allocator_type; 92 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type; 93 typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare; 94 typedef Compare key_compare; 95 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::iterator) iterator; 96 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_iterator) const_iterator; 97 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::reverse_iterator) reverse_iterator; 98 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_reverse_iterator) const_reverse_iterator; 99 typedef std::pair<key_type, mapped_type> nonconst_value_type; 100 typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type; 101 102 map(): m_tree() 103 { 104 //Allocator type must be std::pair<CONST Key, T> 105 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 106 } 107 108 explicit map(const Compare& comp,const allocator_type& a = allocator_type()): m_tree(comp, a) 109 { 110 //Allocator type must be std::pair<CONST Key, T> 111 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 112 } 113 114 template <class InputIterator> 115 map(InputIterator first, InputIterator last, const Compare& comp = Compare(),const allocator_type& a = allocator_type()) 116 : m_tree(true, first, last, comp, a) 117 { 118 //Allocator type must be std::pair<CONST Key, T> 119 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 120 } 121 122 template <class InputIterator> 123 map( ordered_unique_range_t, InputIterator first, InputIterator last 124 , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) 125 : m_tree(ordered_range, first, last, comp, a) 126 { 127 //Allocator type must be std::pair<CONST Key, T> 128 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 129 } 130 map(const map& x): m_tree(x.m_tree) 131 { 132 //Allocator type must be std::pair<CONST Key, T> 133 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 134 } 135 136 map(BOOST_RV_REF(map) x): m_tree(boost::move(x.m_tree)) 137 { 138 //Allocator type must be std::pair<CONST Key, T> 139 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 140 } 141 142 map(const map& x, const allocator_type &a): m_tree(x.m_tree, a) 143 { 144 //Allocator type must be std::pair<CONST Key, T> 145 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 146 } 147 148 map(BOOST_RV_REF(map) x, const allocator_type &a): m_tree(boost::move(x.m_tree), a) 149 { 150 //Allocator type must be std::pair<CONST Key, T> 151 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 152 } 153 map& operator=(BOOST_COPY_ASSIGN_REF(map) x) 154 { m_tree = x.m_tree; return *this; } 155 156 map& operator=(BOOST_RV_REF(map) x) 157 { m_tree = boost::move(x.m_tree); return *this; } 158 159 allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT 160 { return m_tree.get_allocator(); } 161 162 163 stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT 164 { return m_tree.get_stored_allocator(); } 165 166 const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT 167 { return m_tree.get_stored_allocator(); } 168 169 iterator begin() BOOST_CONTAINER_NOEXCEPT 170 { return m_tree.begin(); } 171 172 const_iterator begin() const BOOST_CONTAINER_NOEXCEPT 173 { return this->cbegin(); } 174 175 iterator end() BOOST_CONTAINER_NOEXCEPT 176 { return m_tree.end(); } 177 178 const_iterator end() const BOOST_CONTAINER_NOEXCEPT 179 { return this->cend(); } 180 181 reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT 182 { return m_tree.rbegin(); } 183 184 const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT 185 { return this->crbegin(); } 186 187 reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT 188 { return m_tree.rend(); } 189 190 const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT 191 { return this->crend(); } 192 193 const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT 194 { return m_tree.begin(); } 195 196 const_iterator cend() const BOOST_CONTAINER_NOEXCEPT 197 { return m_tree.end(); } 198 199 const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT 200 { return m_tree.rbegin(); } 201 202 const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT 203 { return m_tree.rend(); } 204 205 bool empty() const BOOST_CONTAINER_NOEXCEPT 206 { return m_tree.empty(); } 207 208 size_type size() const BOOST_CONTAINER_NOEXCEPT 209 { return m_tree.size(); } 210 211 size_type max_size() const BOOST_CONTAINER_NOEXCEPT 212 { return m_tree.max_size(); } 213 214 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 215 216 mapped_type& operator[](const key_type &k); 217 218 mapped_type& operator[](key_type &&k); 219 #else 220 BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript) 221 #endif 222 223 T& at(const key_type& k) 224 { 225 iterator i = this->find(k); 226 if(i == this->end()){ 227 throw_out_of_range("map::at key not found"); 228 } 229 return i->second; 230 } 231 232 const T& at(const key_type& k) const 233 { 234 const_iterator i = this->find(k); 235 if(i == this->end()){ 236 throw_out_of_range("map::at key not found"); 237 } 238 return i->second; 239 } 240 241 std::pair<iterator,bool> insert(const value_type& x) 242 { return m_tree.insert_unique(x); } 243 244 std::pair<iterator,bool> insert(const nonconst_value_type& x) 245 { return m_tree.insert_unique(x); } 246 247 std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_value_type) x) 248 { return m_tree.insert_unique(boost::move(x)); } 249 250 std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x) 251 { return m_tree.insert_unique(boost::move(x)); } 252 253 std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x) 254 { return m_tree.insert_unique(boost::move(x)); } 255 256 iterator insert(const_iterator position, const value_type& x) 257 { return m_tree.insert_unique(position, x); } 258 259 iterator insert(const_iterator position, BOOST_RV_REF(nonconst_value_type) x) 260 { return m_tree.insert_unique(position, boost::move(x)); } 261 262 iterator insert(const_iterator position, BOOST_RV_REF(movable_value_type) x) 263 { return m_tree.insert_unique(position, boost::move(x)); } 264 265 iterator insert(const_iterator position, const nonconst_value_type& x) 266 { return m_tree.insert_unique(position, x); } 267 268 iterator insert(const_iterator position, BOOST_RV_REF(value_type) x) 269 { return m_tree.insert_unique(position, boost::move(x)); } 270 271 template <class InputIterator> 272 void insert(InputIterator first, InputIterator last) 273 { m_tree.insert_unique(first, last); } 274 275 #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 276 277 template <class... Args> 278 std::pair<iterator,bool> emplace(Args&&... args) 279 { return m_tree.emplace_unique(boost::forward<Args>(args)...); } 280 281 template <class... Args> 282 iterator emplace_hint(const_iterator hint, Args&&... args) 283 { return m_tree.emplace_hint_unique(hint, boost::forward<Args>(args)...); } 284 285 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 286 287 #define BOOST_PP_LOCAL_MACRO(n) \ 288 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 289 std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 290 { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ 291 \ 292 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 293 iterator emplace_hint(const_iterator hint \ 294 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 295 { return m_tree.emplace_hint_unique(hint \ 296 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \ 297 //! 298 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) 299 #include BOOST_PP_LOCAL_ITERATE() 300 301 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 302 303 iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT 304 { return m_tree.erase(position); } 305 306 size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT 307 { return m_tree.erase(x); } 308 309 iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT 310 { return m_tree.erase(first, last); } 311 312 void swap(map& x) 313 { m_tree.swap(x.m_tree); } 314 315 void clear() BOOST_CONTAINER_NOEXCEPT 316 { m_tree.clear(); } 317 318 key_compare key_comp() const 319 { return m_tree.key_comp(); } 320 321 value_compare value_comp() const 322 { return value_compare(m_tree.key_comp()); } 323 324 iterator find(const key_type& x) 325 { return m_tree.find(x); } 326 327 const_iterator find(const key_type& x) const 328 { return m_tree.find(x); } 329 330 size_type count(const key_type& x) const 331 { return m_tree.find(x) == m_tree.end() ? 0 : 1; } 332 333 iterator lower_bound(const key_type& x) 334 { return m_tree.lower_bound(x); } 335 336 const_iterator lower_bound(const key_type& x) const 337 { return m_tree.lower_bound(x); } 338 339 iterator upper_bound(const key_type& x) 340 { return m_tree.upper_bound(x); } 341 342 const_iterator upper_bound(const key_type& x) const 343 { return m_tree.upper_bound(x); } 344 345 std::pair<iterator,iterator> equal_range(const key_type& x) 346 { return m_tree.equal_range(x); } 347 348 std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const 349 { return m_tree.equal_range(x); } 350 351 template <class K1, class T1, class C1, class A1> 352 friend bool operator== (const map<K1, T1, C1, A1>&, 353 const map<K1, T1, C1, A1>&); 354 template <class K1, class T1, class C1, class A1> 355 friend bool operator< (const map<K1, T1, C1, A1>&, 356 const map<K1, T1, C1, A1>&); 357 private: 358 mapped_type& priv_subscript(const key_type &k) 359 { 360 //we can optimize this 361 iterator i = lower_bound(k); 362 // i->first is greater than or equivalent to k. 363 if (i == end() || key_comp()(k, (*i).first)){ 364 container_detail::value_init<mapped_type> m; 365 movable_value_type val(k, boost::move(m.m_t)); 366 i = insert(i, boost::move(val)); 367 } 368 return (*i).second; 369 } 370 371 mapped_type& priv_subscript(BOOST_RV_REF(key_type) mk) 372 { 373 key_type &k = mk; 374 //we can optimize this 375 iterator i = lower_bound(k); 376 // i->first is greater than or equivalent to k. 377 if (i == end() || key_comp()(k, (*i).first)){ 378 container_detail::value_init<mapped_type> m; 379 movable_value_type val(boost::move(k), boost::move(m.m_t)); 380 i = insert(i, boost::move(val)); 381 } 382 return (*i).second; 383 } 384 385 /// @endcond 386 }; 387 388 template <class Key, class T, class Compare, class Allocator> 389 inline bool operator==(const map<Key,T,Compare,Allocator>& x, 390 const map<Key,T,Compare,Allocator>& y) 391 { return x.m_tree == y.m_tree; } 392 template <class Key, class T, class Compare, class Allocator> 393 inline bool operator<(const map<Key,T,Compare,Allocator>& x, 394 const map<Key,T,Compare,Allocator>& y) 395 { return x.m_tree < y.m_tree; } 396 template <class Key, class T, class Compare, class Allocator> 397 inline bool operator!=(const map<Key,T,Compare,Allocator>& x, 398 const map<Key,T,Compare,Allocator>& y) 399 { return !(x == y); } 400 template <class Key, class T, class Compare, class Allocator> 401 inline bool operator>(const map<Key,T,Compare,Allocator>& x, 402 const map<Key,T,Compare,Allocator>& y) 403 { return y < x; } 404 template <class Key, class T, class Compare, class Allocator> 405 inline bool operator<=(const map<Key,T,Compare,Allocator>& x, 406 const map<Key,T,Compare,Allocator>& y) 407 { return !(y < x); } 408 template <class Key, class T, class Compare, class Allocator> 409 inline bool operator>=(const map<Key,T,Compare,Allocator>& x, 410 const map<Key,T,Compare,Allocator>& y) 411 { return !(x < y); } 412 template <class Key, class T, class Compare, class Allocator> 413 inline void swap(map<Key,T,Compare,Allocator>& x, map<Key,T,Compare,Allocator>& y) 414 { x.swap(y); } 415 /// @cond 416 417 // Forward declaration of operators < and ==, needed for friend declaration. 418 419 template <class Key, class T, class Compare, class Allocator> 420 inline bool operator==(const multimap<Key,T,Compare,Allocator>& x, 421 const multimap<Key,T,Compare,Allocator>& y); 422 423 template <class Key, class T, class Compare, class Allocator> 424 inline bool operator<(const multimap<Key,T,Compare,Allocator>& x, 425 const multimap<Key,T,Compare,Allocator>& y); 426 427 } //namespace container { 428 429 template <class K, class T, class C, class Allocator> 430 struct has_trivial_destructor_after_move<boost::container::map<K, T, C, Allocator> > 431 { 432 static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; 433 }; 434 435 namespace container { 436 437 438 //! A multimap is a kind of associative container that supports equivalent keys 439 //! (possibly containing multiple copies of the same key value) and provides for 440 //! fast retrieval of values of another type T based on the keys. The multimap class 441 //! supports bidirectional iterators. 442 //! 443 //! A multimap satisfies all of the requirements of a container and of a reversible 444 //! container and of an associative container. For a 445 //! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>. 446 //! 447 //! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). 448 //! 449 //! Allocator is the allocator to allocate the value_types 450 //!(e.g. <i>allocator< std::pair<<b>const</b> Key, T> ></i>). 451 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED 452 template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< const Key, T> > > 453 #else 454 template <class Key, class T, class Compare, class Allocator> 455 #endif 456 class multimap 457 { 458 /// @cond 459 private: 460 BOOST_COPYABLE_AND_MOVABLE(multimap) 461 462 typedef std::pair<const Key, T> value_type_impl; 463 typedef container_detail::rbtree 464 <Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator> tree_t; 465 typedef container_detail::pair <Key, T> movable_value_type_impl; 466 typedef container_detail::tree_value_compare 467 < Key, value_type_impl, Compare, container_detail::select1st<value_type_impl> 468 > value_compare_impl; 469 tree_t m_tree; // red-black tree representing map 470 /// @endcond 471 472 public: 473 typedef Key key_type; 474 typedef T mapped_type; 475 typedef std::pair<const Key, T> value_type; 476 typedef typename boost::container::allocator_traits<Allocator>::pointer pointer; 477 typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer; 478 typedef typename boost::container::allocator_traits<Allocator>::reference reference; 479 typedef typename boost::container::allocator_traits<Allocator>::const_reference const_reference; 480 typedef typename boost::container::allocator_traits<Allocator>::size_type size_type; 481 typedef typename boost::container::allocator_traits<Allocator>::difference_type difference_type; 482 typedef Allocator allocator_type; 483 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type; 484 typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare; 485 typedef Compare key_compare; 486 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::iterator) iterator; 487 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_iterator) const_iterator; 488 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::reverse_iterator) reverse_iterator; 489 typedef typename BOOST_CONTAINER_IMPDEF(tree_t::const_reverse_iterator) const_reverse_iterator; 490 typedef std::pair<key_type, mapped_type> nonconst_value_type; 491 typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type; 492 493 multimap(): m_tree() 494 { 495 //Allocator type must be std::pair<CONST Key, T> 496 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 497 } 498 499 explicit multimap(const Compare& comp, const allocator_type& a = allocator_type()): m_tree(comp, a) 500 { 501 //Allocator type must be std::pair<CONST Key, T> 502 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 503 } 504 505 template <class InputIterator> 506 multimap(InputIterator first, InputIterator last, 507 const Compare& comp = Compare(), 508 const allocator_type& a = allocator_type()) 509 : m_tree(false, first, last, comp, a) 510 { 511 //Allocator type must be std::pair<CONST Key, T> 512 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 513 } 514 515 template <class InputIterator> 516 multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(), 517 const allocator_type& a = allocator_type()) 518 : m_tree(ordered_range, first, last, comp, a) 519 {} 520 521 multimap(const multimap& x): m_tree(x.m_tree) 522 { 523 //Allocator type must be std::pair<CONST Key, T> 524 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 525 } 526 527 multimap(BOOST_RV_REF(multimap) x): m_tree(boost::move(x.m_tree)) 528 { 529 //Allocator type must be std::pair<CONST Key, T> 530 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 531 } 532 533 multimap(const multimap& x, const allocator_type &a): m_tree(x.m_tree, a) 534 { 535 //Allocator type must be std::pair<CONST Key, T> 536 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 537 } 538 multimap(BOOST_RV_REF(multimap) x, const allocator_type &a): m_tree(boost::move(x.m_tree), a) 539 { 540 //Allocator type must be std::pair<CONST Key, T> 541 BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); 542 } 543 544 multimap& operator=(BOOST_COPY_ASSIGN_REF(multimap) x) 545 { m_tree = x.m_tree; return *this; } 546 547 multimap& operator=(BOOST_RV_REF(multimap) x) 548 { m_tree = boost::move(x.m_tree); return *this; } 549 550 allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT 551 { return m_tree.get_allocator(); } 552 553 stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT 554 { return m_tree.get_stored_allocator(); } 555 556 const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT 557 { return m_tree.get_stored_allocator(); } 558 559 iterator begin() BOOST_CONTAINER_NOEXCEPT 560 { return m_tree.begin(); } 561 562 const_iterator begin() const BOOST_CONTAINER_NOEXCEPT 563 { return this->cbegin(); } 564 565 iterator end() BOOST_CONTAINER_NOEXCEPT 566 { return m_tree.end(); } 567 568 const_iterator end() const BOOST_CONTAINER_NOEXCEPT 569 { return this->cend(); } 570 571 reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT 572 { return m_tree.rbegin(); } 573 574 const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT 575 { return this->crbegin(); } 576 577 reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT 578 { return m_tree.rend(); } 579 580 const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT 581 { return this->crend(); } 582 583 const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT 584 { return m_tree.begin(); } 585 586 const_iterator cend() const BOOST_CONTAINER_NOEXCEPT 587 { return m_tree.end(); } 588 589 const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT 590 { return m_tree.rbegin(); } 591 592 const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT 593 { return m_tree.rend(); } 594 595 bool empty() const BOOST_CONTAINER_NOEXCEPT 596 { return m_tree.empty(); } 597 598 size_type size() const BOOST_CONTAINER_NOEXCEPT 599 { return m_tree.size(); } 600 601 size_type max_size() const BOOST_CONTAINER_NOEXCEPT 602 { return m_tree.max_size(); } 603 604 #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 605 606 template <class... Args> 607 iterator emplace(Args&&... args) 608 { return m_tree.emplace_equal(boost::forward<Args>(args)...); } 609 610 template <class... Args> 611 iterator emplace_hint(const_iterator hint, Args&&... args) 612 { return m_tree.emplace_hint_equal(hint, boost::forward<Args>(args)...); } 613 614 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 615 616 #define BOOST_PP_LOCAL_MACRO(n) \ 617 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 618 iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 619 { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ 620 \ 621 BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ 622 iterator emplace_hint(const_iterator hint \ 623 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ 624 { return m_tree.emplace_hint_equal(hint \ 625 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \ 626 //! 627 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) 628 #include BOOST_PP_LOCAL_ITERATE() 629 630 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING 631 632 iterator insert(const value_type& x) 633 { return m_tree.insert_equal(x); } 634 635 iterator insert(const nonconst_value_type& x) 636 { return m_tree.insert_equal(x); } 637 638 iterator insert(BOOST_RV_REF(nonconst_value_type) x) 639 { return m_tree.insert_equal(boost::move(x)); } 640 641 iterator insert(BOOST_RV_REF(movable_value_type) x) 642 { return m_tree.insert_equal(boost::move(x)); } 643 644 iterator insert(const_iterator position, const value_type& x) 645 { return m_tree.insert_equal(position, x); } 646 647 iterator insert(const_iterator position, const nonconst_value_type& x) 648 { return m_tree.insert_equal(position, x); } 649 650 iterator insert(const_iterator position, BOOST_RV_REF(nonconst_value_type) x) 651 { return m_tree.insert_equal(position, boost::move(x)); } 652 653 iterator insert(const_iterator position, BOOST_RV_REF(movable_value_type) x) 654 { return m_tree.insert_equal(position, boost::move(x)); } 655 656 template <class InputIterator> 657 void insert(InputIterator first, InputIterator last) 658 { m_tree.insert_equal(first, last); } 659 660 iterator erase(const_iterator position) BOOST_CONTAINER_NOEXCEPT 661 { return m_tree.erase(position); } 662 663 size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT 664 { return m_tree.erase(x); } 665 666 iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT 667 { return m_tree.erase(first, last); } 668 669 void swap(multimap& x) 670 { m_tree.swap(x.m_tree); } 671 672 void clear() BOOST_CONTAINER_NOEXCEPT 673 { m_tree.clear(); } 674 675 key_compare key_comp() const 676 { return m_tree.key_comp(); } 677 678 value_compare value_comp() const 679 { return value_compare(m_tree.key_comp()); } 680 681 iterator find(const key_type& x) 682 { return m_tree.find(x); } 683 684 const_iterator find(const key_type& x) const 685 { return m_tree.find(x); } 686 687 size_type count(const key_type& x) const 688 { return m_tree.count(x); } 689 690 iterator lower_bound(const key_type& x) 691 {return m_tree.lower_bound(x); } 692 693 const_iterator lower_bound(const key_type& x) const 694 { return m_tree.lower_bound(x); } 695 696 iterator upper_bound(const key_type& x) 697 { return m_tree.upper_bound(x); } 698 699 const_iterator upper_bound(const key_type& x) const 700 { return m_tree.upper_bound(x); } 701 702 std::pair<iterator,iterator> equal_range(const key_type& x) 703 { return m_tree.equal_range(x); } 704 705 std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const 706 { return m_tree.equal_range(x); } 707 708 /// @cond 709 template <class K1, class T1, class C1, class A1> 710 friend bool operator== (const multimap<K1, T1, C1, A1>& x, 711 const multimap<K1, T1, C1, A1>& y); 712 713 template <class K1, class T1, class C1, class A1> 714 friend bool operator< (const multimap<K1, T1, C1, A1>& x, 715 const multimap<K1, T1, C1, A1>& y); 716 /// @endcond 717 }; 718 719 template <class Key, class T, class Compare, class Allocator> 720 inline bool operator==(const multimap<Key,T,Compare,Allocator>& x, 721 const multimap<Key,T,Compare,Allocator>& y) 722 { return x.m_tree == y.m_tree; } 723 724 template <class Key, class T, class Compare, class Allocator> 725 inline bool operator<(const multimap<Key,T,Compare,Allocator>& x, 726 const multimap<Key,T,Compare,Allocator>& y) 727 { return x.m_tree < y.m_tree; } 728 729 template <class Key, class T, class Compare, class Allocator> 730 inline bool operator!=(const multimap<Key,T,Compare,Allocator>& x, 731 const multimap<Key,T,Compare,Allocator>& y) 732 { return !(x == y); } 733 734 template <class Key, class T, class Compare, class Allocator> 735 inline bool operator>(const multimap<Key,T,Compare,Allocator>& x, 736 const multimap<Key,T,Compare,Allocator>& y) 737 { return y < x; } 738 739 template <class Key, class T, class Compare, class Allocator> 740 inline bool operator<=(const multimap<Key,T,Compare,Allocator>& x, 741 const multimap<Key,T,Compare,Allocator>& y) 742 { return !(y < x); } 743 744 template <class Key, class T, class Compare, class Allocator> 745 inline bool operator>=(const multimap<Key,T,Compare,Allocator>& x, 746 const multimap<Key,T,Compare,Allocator>& y) 747 { return !(x < y); } 748 749 template <class Key, class T, class Compare, class Allocator> 750 inline void swap(multimap<Key,T,Compare,Allocator>& x, multimap<Key,T,Compare,Allocator>& y) 751 { x.swap(y); } 752 753 /// @cond 754 755 } //namespace container { 756 757 //!has_trivial_destructor_after_move<> == true_type 758 //!specialization for optimizations 759 template <class K, class T, class C, class Allocator> 760 struct has_trivial_destructor_after_move<boost::container::multimap<K, T, C, Allocator> > 761 { 762 static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; 763 }; 764 765 namespace container { 766 767 /// @endcond 768 769 }} 770 #include <boost/container/detail/config_end.hpp> 771 #endif /* BOOST_CONTAINER_MAP_HPP */
- A pair Associative Container is an Associative Container that associates a key with some other object. The value type of a Pair Associative Container is pair<const key_type, data_type>.
- Models: map; multimap; hash_map; hash_multimap
- The value type must be pair<const key_type, data_type>, rather than pair<key_type, data_type>, because of the Associative Container invariant of key immutability. The data_type part of an object in a Pair Associative Container may be modified, but the key_type part may not be. Note the implication of this fact: a Pair Associative Container can not provide mutable iterators (as defined in the Trivial Iterator requirements), because the value type of a mutable iterator must be Assignable, and pair<const key_type,data_type> is not Assignable. However, a Pair Associative Container can provide iteratoers that are not completely constant: iterators such that the expression (*i).second = d is valid.
- Key type: X::key_type The type of the key associated with X::value_type.
- Data type: X::data_type The type of the data associated with X::value_type. A Pair Associative Container can be thought of as a mapping from key_type to data_type.
- Value type: X::value_type The type of object stored in the container. The value type is required to be pair<const key_type, data_type>.
Associative Container->Sorted Associative Container
- A Sorted Associative Container is a type of Associative Container. Sorted Associative Containers use an ordering relation on their keys; two keys are considered to be equivalent if neither one is less than the other. (If the ordering relation is case-insensitive string comparison, for example, then the keys “abcde” and “aBCde” are equivalent.)
- Sorted Associative Containers guarantee that the complexity for most operations is never worse than logarithmic(对数), and they also guarantee that their elements are always sorted in ascending order by key. (descending order)
- Two new types are introduced, in addition to the types defined in the Associative Container and Reversible Container requirements.
- X::key_compare The type of a Strict Weak Ordering used to compare keys. Its argument type must be X::key_type.
- X::value_compare The type of a Strict Weak Ordering used to compare values. Its argument type must be X::value_type, and it compares two objects of value_type by passing the keys associated with those objects to a function object of type key_compare.
- Complexity guarantees: key_comp() and value_comp() are constant time. Erase element is constant time. Erase key is O (log(size()) + count (k) ). Erase range is O (log (size() ) + N ), where N is the length of the range. Find is logarithmic. Count is O (log (size() ) + count (k). Lower bound, upper bound, and equal range are logarithmic.
- Definition of value_comp: If t1 and t2 are objects of type X:: value_type and k1 and k2 are the keys associated with those objects, then a,value_comp() returns a function object such that a.value_com() (t1, t2) is equivalent to a.key_comp(k1,k2).
- Ascending order: The elements in a Sorted Associative Container are always arranged in ascending order by key. That is, if a is a Sorted Associative Container, then is_sorted( a.begin(), a.end() ), a.value_comp() ) is always true.
- Models: set; multiset; map; multimap
- This is a much stronger guarantee than the one provided by Associative Container. The guarantees in Associative Container only apply to average complexity; worst case complexity is allowed to be greater. Sorted Associative Container, however, provides an upper limit on worst case complexity.
- This definition is consistent with the semantics described in Associative Container. It is stronger condition, though: if a contains no elements with the key k, then a.equal_range (k) returns an empty range that indicates the position where those elements would be if they did exist. The Associative Container requirements, however, merely state that the return value is an arbitrary( 1. determined by changce, whim or impulse, and not by necessity ,reason, or principle; 2. Based on or subject to individual judgment or preference) empty range.
Associative Container->Hashed Associative Container
- A Hashed Associative Container is an Associative Container whose implementation is a hash table. The elements of a Hashed Associative Container are not guaranteed to be in any meaningful order, in particular, they are not sorted. The worst case complexity of most operations on Hashed Associative is linear in the size of the container, but the average case complexity is constant time; this means that for applications where values are simply stored and retrieved, and where ordering is unimportant, Hashed Associative Containers are usually much faster than Sorted Associative Containers.
- Hash function X::hasher A type that is a model of Hash Function X::hasher’s argument type must be X::key_type.
- Key equal X::key_equal A Binary_Predicate whose argument type is X::key_type. An object of type key_equal returns true if its arguments are the same key, and false otherwise, X::key_equal must be an equivalence relation.
- A hash function for a Hased Associative Container X is a Unary Function with argument X::key_type and whose return type is size_t. A hash function must be deterministic ( that is, it must always return the same value whenever it is called with the same argument), but return values of the hash function should be as uniform as possible: ideally, no two keys will hash to the same value.
- Elements in a Hashed Associative Container are organized into buckets. A Hashed Associative Container uses the value of the hash function to determine which bucket an element is assigned to.
- The number of elements in a Hashed Associative Container divided by the number of buckets is called the load factor. A Hashed Associative Container with a small load factor is faster than one with a large load factor.
- The default constructor, constructor with bucket count, constructor with hash function, and constructor with key equal, are all amortized constant time.
- Hash Function and Key Equal are amortized constant time.
- Average complexity for Erase key is O(count(k). Worst case is linear in the size of the container.
- Erase Element is amortized constant time. Average complexity for Erase Range is O(N), where N is the length of the range being erased. Worse case is linear in the size of the container.
- Average complexity for Find is constant time. Worst case is linear in the size of the container. Resize is linear in the size of the container.
- Models: hash_set; hash_map; hash_multiset; hash_multimap.
- There is an extensive literature dealing with hash tables. If the hash function is poor( that is, if many different keys hash to the same value) then this will hurt performance. The worst case is where every key hashes to the same value, in this case, run-time complexity of most Hashed Associative Container operations will be liner in the size of the container.
- Resizing does not invalidate iterators; however, it does not necessarily preserve the ordering relation between iterators. That is, if I and j are iterators that point into a Hashed Associative Container such that I comes immediately before j, then there is no guarantee that I will still come immediately before j after the container is resized. The only guarantee about the ordering of elements is the contiguous storage invariant: elements with the same key are always adjacent to each other.
Sequences->Vector
- A vector is a Sequence that supports random access to elements, constant time insertion and removal of elements at the end, and linear time insertion and removal of elements at the beginning or in the middle. The number of elements in a vector may vary dynamically; memory management is automatic. Vector is the simplest of the STL container classes, and in many cases the most efficient.
- This member function relies on member template functions, which at present are not supported by all compilers. If your compiler supports member templates, you can call this function with any type of input_iterator. If your compiler does not yet supports member templates, though, then the arguments must be of type const value_type*
- Memory will be reallocated automatically if more than capacity() – size() elements are inserted into the vector. Reallocation does not change size(), nor does it change the values of any elements of the vector. It does, however, increase capacity(), and it invalidates any iterators that point into the vector.
- When it is necessary to increase capacity(), vector usually increases it by a factor of two. It is crucial that the amount of growth is proportional to the current capacity(), rather than a fixed constant: in the former case inserting a series of elements into a vector is a linear time operation, and in the latter case it is quadratic (of, relating to or containing quantities of the second degree).
- Reserve() causes a reallocation manually. The main reason for using reserve() is efficiency. If you know the capacity to which your vector must eventually grow, then it is usually more efficient to allocate that memory all at once rather than relying on the automatic reallocation scheme. The other reason for using reserve() is so that you can control the invalidation of iterator.
- A vector’s iterators are invalidated when its memory is reallocated. Additionally, inserting or deleting an element in the middle of a vector invalidates all iterators that point to elements following the insertion or deletion point. It follows that you can prevent a vector’s iterators from being invalidates if you use reserve() to preallocate as much memory as vector will ever use, and if all insertions and deletions are at the vector’s end.
Sequences->deque
- A deque is very much like a vector, it is a sequence that supports random access to elements, constant time insertion and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle.
- The main way in which differs from vector is that deque also supports constant time insertion and removal of element at the beginning of the sequence. Additionally, deque does not have any member functions analogous/similar to vector’s capacity() and reserve(), and does not provide any of the guarantees on iterator validity that are associated with those member functions.
- The name deque is pronounced “deck”, and stands for “double-ended queue.”
- Inserting an element at the beginning or end of a deque takes amortized constant time. Inserting an element in the middle is linear in n, where n is the smaller of the number of elements from the insertion point to the beginning and the number of elements from the insertion point to the end.
- The semantics of iterator invalidation for deque is as follows. Insert(including push_front and push_back) invalidates all iterators that refer to a deque. Erase in the middle /midst of a deque invalidates all iterators that refer to the deque. Erase at the beginning or end of a deque (including pop_front and pop_back() )invalidates an iterator only if it points to the erased element.
- This member function relies on member template functions, which at present are not supported by all compilers. If your compiler supports member templates, you can call this function with any type of input_iterator. If your compiler does not yet support member templates, though, then the arguments must either be of type const value_type * or of type deque::const_iterator.
Sequences->list<T, Alloc>
- A list is a doubly linked list. That is, That is to say, Namely, it is a Sequence that supports both forward and backward traversal, and constant time insertion and removal of elements at the beginning or the end, or in the middle. Lists have the important property that insertion and splicing do not invalidate interators 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, list<T>::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.
- Note that singly linked lists, which only support forward traversal, are also sometimes useful. If you do not need backward traversal, then slist may be more efficient than list.
- A comparison with vector is instructive. Suppose that I is a valid vector<T>::iterator. If an element is inserted or removed in a position that precedes I, then this operation will either result in I pointing to a different element than it did before, or else it will invalidate I entirely.
- A vector<T>::iterator will be invalidated if an insertion requires a reallocation.
- However, suppose that I and j are both iterators into a vector, and there exists some integer n such that I == j + n. In that case, even if elements are inserted into to vector and I and j point to different elements, the relation between iterators will still hold.
- A list is exactly the opposite: iterators predecessor/successor relationship is not invariant.
- A similar property holds for all version of insert() and erase(). List <T, Alloc>:: insert never invalidates any iterator, and erase() only invalidates iterators pointing to the elements that are actually being erased.
- If L is a list, note that L.reverse() and reverse(L.begin(), L.end() ) are both correct ways of reversing the list. They differ in that L.reverse() will preserve the values that each iterator into L points to but will not preserve the iterators’ predecessor/successor relationships, while reverse (L.begin(), L.end() ) will not preserve the value that each iterator points to but will preserve the iterators’ predecessor /successor relationships. Note also that algorithm reverse (L.begin(), L.end() ) will use T’s assignment operator, while the member function L.reverse() will not.
- The sort algorithm works only for random access iterators. In principle, however, it would be possible to write a sort algorithm that also accepted bidirectional iterators. Even if there were such a version of sort. It would still be useful for list to have a sort member function. That is, sort is provided as a member function not only for the sake of efficiency, but also because of the property that it preserves the values that list iterators point to.
Associative Container->set<Key, Compare, Alloc>
- Set is a Sorted Associative Container that stores objects of type Key. Set is a Simple Associative Container, meaning that its value type, as well as its key type, is Key. It is also a Unique Associative Container, meaning that no two elements are the same.
- Set and multiset are particular well suited to the set algorithm includes, set_union, set_intersection, set_difference, and set_symetric_difference. The reason for this is twofold/diplex/diploid/double/dual/duple. First, the set algorithms require their arguments to be sorted ranges, and, since set and multiset are Sorted Associative Containers, their elements are always sorted in ascending order. Second, the output range of these algorithms is always sorted, and inserting a sorted range into a set or multiset is a fast operation: the Unique Sorted Associative Container and Multiple Sorted Associative Container requirements guarantee that inserting a range takes only linear time if the range is already sorted.
- Set has the important property that inserting a new element into a set does not invalidate iterators that point to existing element. Erasing an element from a set also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being removed /deleted /cut off /eliminated/got rod of.
- Key: The set’s key type and value type. This is also defined as set::key_type and set::value_type.
- Compare: The Key comparison function, a Strict Weak Ordering whose argument type is key_type; it returns ture if its first argument is less than its second argument, and false otherwise. This is also defined as set::key_compare and set::value_compare.
- Alloc: The set’s allocator, used for all internal memory management.
Associative Container-->map<Key,Data, Compare, Alloc>
- Map is a Sorted Associative Container that associates objects of type Key with objects of type Data. Map is a Pair Associative Container, meaning that its value type is pair<const Key, Data>. It is also a Unique Associative Container, meaning that no two elements have the same key.
- Map has the important property that inserting a new element into a map does not invalidate iterators that point to existing element. Erasing an element from a set also does not invalidate any interators, except, of course, for iterators that actually point to the element that is being erased.
- Compare has the default implementation which is less<key>; less is a template function, just like template <class _Tp>struct less : public binary_function<_Tp,_Tp,tBool> { tBool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y? TRUE:FALSE; }};
- Type requirements: Data is Assignable; Compare is a Strict Weak Ordering whose argument type is key to be as template less argument type. Alloc is an Allocator.
- New members: data_type & operator[ ] (const key_type &k) Returns a reference to the object that is associated with a particular key. If the map does not already contain such an object, operator[ ] inserts the default object data_type().
- Map::iterator is not a mutable iterator, because map::value_type is not Assignable. That is, if I is of type map::iterator and p is of type map::value_type, then *I = p is not valid expression. However, map::iterator is not a constant iterator either, because it can be used to modify the object that it points to. Using the same notation as above, (*i) . second = p is a valid expression. The same point applies to map::reverse_iterator.
- Since operator[ ] might insert a new element into the map, it can’t possibly be a const member function. Note that the definition of operator [ ] is extremely simple: m[k] is equivalent to (* (( m.insert (value_type (k, data_type() ) ) ).first )) . second. Strictly speaking, this member function is unnecessary, it exists only for convenience.
AutoPtr
1 //Forward declaretion, TEMPLATE CLASS auto_ptr 2 template<class _Ty> 3 class auto_ptr; 4 5 template<class _Ty> 6 struct auto_ptr_ref 7 { // proxy reference for auto_ptr copying 8 explicit auto_ptr_ref(_Ty *_Right): _Ref(_Right) 9 { // construct from generic pointer to auto_ptr ptr 10 } 11 _Ty *_Ref; // generic pointer to auto_ptr ptr 12 }; 13 14 template<class _Ty> 15 class auto_ptr 16 { // wrap an object pointer to ensure destruction 17 public: 18 typedef auto_ptr<_Ty> _Myt; 19 typedef _Ty element_type; 20 explicit auto_ptr(_Ty *_Ptr = 0) _THROW0(): _Myptr(_Ptr) 21 { // construct from object pointer 22 } 23 auto_ptr(_Myt& _Right) _THROW0(): _Myptr(_Right.release()) 24 { // construct by assuming pointer from _Right auto_ptr 25 } 26 auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0() 27 { // construct by assuming pointer from _Right auto_ptr_ref 28 _Ty *_Ptr = _Right._Ref; 29 _Right._Ref = 0; // release old 30 _Myptr = _Ptr; // reset this 31 } 32 33 template<class _Other> 34 operator auto_ptr<_Other>() _THROW0() 35 { // convert to compatible auto_ptr 36 return (auto_ptr<_Other>(*this)); 37 } 38 39 template<class _Other> 40 operator auto_ptr_ref<_Other>() _THROW0() 41 { // convert to compatible auto_ptr_ref 42 _Other *_Cvtptr = _Myptr; // test implicit conversion 43 auto_ptr_ref<_Other> _Ans(_Cvtptr); 44 _Myptr = 0; // pass ownership to auto_ptr_ref 45 return (_Ans); 46 } 47 48 template<class _Other> 49 _Myt& operator=(auto_ptr<_Other>& _Right) _THROW0() 50 { // assign compatible _Right (assume pointer) 51 reset(_Right.release()); 52 return (*this); 53 } 54 55 template<class _Other> 56 auto_ptr(auto_ptr<_Other>& _Right) _THROW0() 57 : _Myptr(_Right.release()) 58 { // construct by assuming pointer from _Right 59 } 60 61 _Myt& operator=(_Myt& _Right) _THROW0() 62 { // assign compatible _Right (assume pointer) 63 reset(_Right.release()); 64 return (*this); 65 } 66 67 _Myt& operator=(auto_ptr_ref<_Ty> _Right) _THROW0() 68 { // assign compatible _Right._Ref (assume pointer) 69 _Ty *_Ptr = _Right._Ref; 70 _Right._Ref = 0; // release old 71 reset(_Ptr); // set new 72 return (*this); 73 } 74 75 ~auto_ptr() 76 { // destroy the object 77 delete _Myptr; 78 } 79 80 _Ty& operator*() const _THROW0() 81 { // return designated value 82 #if _ITERATOR_DEBUG_LEVEL == 2 83 if (_Myptr == 0) 84 _DEBUG_ERROR("auto_ptr not dereferencable"); 85 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */ 86 87 return (*get()); 88 } 89 90 _Ty *operator->() const _THROW0() 91 { // return pointer to class object 92 #if _ITERATOR_DEBUG_LEVEL == 2 93 if (_Myptr == 0) 94 _DEBUG_ERROR("auto_ptr not dereferencable"); 95 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */ 96 97 return (get()); 98 } 99 100 _Ty *get() const _THROW0() 101 { // return wrapped pointer 102 return (_Myptr); 103 } 104 _Ty *release() _THROW0() 105 { // return wrapped pointer and give up ownership 106 _Ty *_Tmp = _Myptr; 107 _Myptr = 0; 108 return (_Tmp); 109 } 110 111 void reset(_Ty *_Ptr = 0) 112 { // destroy designated object and store new pointer 113 if (_Ptr != _Myptr) 114 delete _Myptr; 115 _Myptr = _Ptr; 116 } 117 private: 118 _Ty *_Myptr; // the wrapped object pointer 119 }; 120 _STD_END
Allocator
1 // xmemory internal header (from <memory>) 2 #pragma once 3 #ifndef _XMEMORY_ 4 #define _XMEMORY_ 5 #ifndef RC_INVOKED 6 #include <cstdlib> 7 #include <new> 8 #include <xutility> 9 10 #pragma pack(push,_CRT_PACKING) 11 #pragma warning(push,3) 12 13 14 #pragma push_macro("new") 15 #undef new 16 17 #pragma warning(disable: 4100) 18 19 #ifndef _FARQ /* specify standard memory model */ 20 #define _FARQ 21 #define _PDFT ptrdiff_t 22 #define _SIZT size_t 23 #endif /* _FARQ */ 24 25 _STD_BEGIN 26 // TEMPLATE FUNCTION _Allocate 27 template<class _Ty> inline _Ty _FARQ *_Allocate(_SIZT _Count, _Ty _FARQ *) 28 { // allocate storage for _Count elements of type _Ty 29 void *_Ptr = 0; 30 if (_Count <= 0) 31 _Count = 0; 32 else if (((_SIZT)(-1) / sizeof (_Ty) < _Count) 33 || (_Ptr = ::operator new(_Count * sizeof (_Ty))) == 0) 34 _THROW_NCEE(bad_alloc, 0); 35 return ((_Ty _FARQ *)_Ptr); 36 } 37 38 // TEMPLATE FUNCTION _Construct 39 template<class _Ty1, 40 class _Ty2> inline 41 void _Construct(_Ty1 _FARQ *_Ptr, _Ty2&& _Val) 42 { // construct object at _Ptr with value _Val 43 void _FARQ *_Vptr = _Ptr; 44 ::new (_Vptr) _Ty1(_STD forward<_Ty2>(_Val)); 45 } 46 47 template<class _Ty1> inline 48 void _Construct(_Ty1 _FARQ *_Ptr) 49 { // construct object at _Ptr with default value 50 void _FARQ *_Vptr = _Ptr; 51 ::new (_Vptr) _Ty1(); 52 } 53 54 // TEMPLATE FUNCTION _Destroy 55 template<class _Ty> inline 56 void _Destroy(_Ty _FARQ *_Ptr) 57 { // destroy object at _Ptr 58 _Ptr->~_Ty(); 59 } 60 61 template<> inline 62 void _Destroy(char _FARQ *) 63 { // destroy a char (do nothing) 64 } 65 66 template<> inline 67 void _Destroy(wchar_t _FARQ *) 68 { // destroy a wchar_t (do nothing) 69 } 70 71 #ifdef _NATIVE_WCHAR_T_DEFINED 72 template<> inline 73 void _Destroy(unsigned short _FARQ *) 74 { // destroy a unsigned short (do nothing) 75 } 76 #endif /* _NATIVE_WCHAR_T_DEFINED */ 77 78 // TEMPLATE FUNCTION _Destroy_range 79 template<class _Alloc> inline 80 void _Destroy_range(typename _Alloc::pointer _First,typename _Alloc::pointer _Last, _Alloc& _Al) 81 { // destroy [_First, _Last) 82 _Destroy_range(_First, _Last, _Al, _Ptr_cat(_First, _Last)); 83 } 84 85 template<class _Alloc> inline 86 void _Destroy_range(typename _Alloc::pointer _First,typename _Alloc::pointer _Last, _Alloc& _Al, 87 _Nonscalar_ptr_iterator_tag) 88 { // destroy [_First, _Last), arbitrary type 89 for (; _First != _Last; ++_First) 90 _Dest_val(_Al, _First); 91 } 92 93 template<class _Alloc> inline 94 void _Destroy_range(typename _Alloc::pointer _First,typename _Alloc::pointer _Last, _Alloc& _Al, 95 _Scalar_ptr_iterator_tag) 96 { // destroy [_First, _Last), scalar type (do nothing) 97 } 98 99 // TEMPLATE FUNCTION addressof 100 template<class _Ty> inline 101 _Ty * addressof(_Ty& _Val) 102 { // return address of _Val 103 ((_Ty *) &(char&)_Val); 104 } 105 106 // TEMPLATE CLASS _Allocator_base 107 template<class _Ty> 108 struct _Allocator_base 109 { // base class for generic allocators 110 typedef _Ty value_type; 111 }; 112 113 // TEMPLATE CLASS _Allocator_base<const _Ty> 114 template<class _Ty> 115 struct _Allocator_base<const _Ty> 116 { // base class for generic allocators for const _Ty 117 typedef _Ty value_type; 118 }; 119 120 // TEMPLATE CLASS allocator 121 template<class _Ty> 122 class allocator: public _Allocator_base<_Ty> 123 { // generic allocator for objects of class _Ty 124 public: 125 typedef _Allocator_base<_Ty> _Mybase; 126 typedef typename _Mybase::value_type value_type; 127 128 typedef value_type _FARQ *pointer; 129 typedef value_type _FARQ& reference; 130 typedef const value_type _FARQ *const_pointer; 131 typedef const value_type _FARQ& const_reference; 132 133 typedef _SIZT size_type; 134 typedef _PDFT difference_type; 135 136 template<class _Other> 137 struct rebind 138 { // convert this type to allocator<_Other> 139 typedef allocator<_Other> other; 140 }; 141 142 pointer address(reference _Val) const 143 { // return address of mutable _Val 144 return ((pointer) &(char&)_Val); 145 } 146 const_pointer address(const_reference _Val) const 147 { // return address of nonmutable _Val 148 return ((const_pointer) &(char&)_Val); 149 } 150 allocator() _THROW0() 151 { // construct default allocator (do nothing) 152 } 153 154 allocator(const allocator<_Ty>&) _THROW0() 155 { // construct by copying (do nothing) 156 } 157 158 template<class _Other> 159 allocator(const allocator<_Other>&) _THROW0() 160 { // construct from a related allocator (do nothing) 161 } 162 163 template<class _Other> 164 allocator<_Ty>& operator=(const allocator<_Other>&) 165 { // assign from a related allocator (do nothing) 166 return (*this); 167 } 168 169 void deallocate(pointer _Ptr, size_type) 170 { // deallocate object at _Ptr, ignore size 171 ::operator delete(_Ptr); 172 } 173 pointer allocate(size_type _Count) 174 { // allocate array of _Count elements 175 return (_Allocate(_Count, (pointer)0)); 176 } 177 pointer allocate(size_type _Count, const void _FARQ *) 178 { // allocate array of _Count elements, ignore hint 179 return (allocate(_Count)); 180 } 181 void construct(pointer _Ptr, const _Ty& _Val) 182 { // construct object at _Ptr with value _Val 183 _Construct(_Ptr, _Val); 184 } 185 void construct(pointer _Ptr, _Ty&& _Val) 186 { // construct object at _Ptr with value _Val 187 ::new ((void _FARQ *)_Ptr) _Ty(_STD forward<_Ty>(_Val)); 188 } 189 190 template<class _Other> 191 void construct(pointer _Ptr, _Other&& _Val) 192 { // construct object at _Ptr with value _Val 193 ::new ((void _FARQ *)_Ptr) _Ty(_STD forward<_Other>(_Val)); 194 } 195 196 void destroy(pointer _Ptr) 197 { // destroy object at _Ptr 198 _Destroy(_Ptr); 199 } 200 201 _SIZT max_size() const _THROW0() 202 { // estimate maximum array size 203 _SIZT _Count = (_SIZT)(-1) / sizeof (_Ty); 204 return (0 < _Count ? _Count : 1); 205 } 206 }; 207 208 // CLASS allocator<void> 209 template<> class allocator<void> 210 { // generic allocator for type void 211 public: 212 typedef void _Ty; 213 typedef _Ty _FARQ *pointer; 214 typedef const _Ty _FARQ *const_pointer; 215 typedef _Ty value_type; 216 217 template<class _Other> 218 struct rebind 219 { // convert this type to an allocator<_Other> 220 typedef allocator<_Other> other; 221 }; 222 223 allocator() _THROW0() 224 { // construct default allocator (do nothing) 225 } 226 227 allocator(const allocator<_Ty>&) _THROW0() 228 { // construct by copying (do nothing) 229 } 230 231 template<class _Other> 232 allocator(const allocator<_Other>&) _THROW0() 233 { // construct from related allocator (do nothing) 234 } 235 236 template<class _Other> 237 allocator<_Ty>& operator=(const allocator<_Other>&) 238 { // assign from a related allocator (do nothing) 239 return (*this); 240 } 241 }; 242 243 template<class _Ty,class _Other> inline 244 bool operator==(const allocator<_Ty>&,const allocator<_Other>&) _THROW0() 245 { // test for allocator equality 246 return (true); 247 } 248 template<class _Ty,class _Other> 249 inline bool operator!=(const allocator<_Ty>& _Left,const allocator<_Other>& _Right) _THROW0() 250 { // test for allocator inequality 251 return (!(_Left == _Right)); 252 } 253 254 // TEMPLATE FUNCTIONS _Cons_val AND _Dest_val 255 template<class _Alloc,class _Ty1,class _Ty2> 256 void _Cons_val(_Alloc& _Alval, _Ty1 *_Pdest, _Ty2&& _Src) 257 { // construct using allocator 258 _Alval.construct(_Pdest, _STD forward<_Ty2>(_Src)); 259 } 260 261 template<class _Alloc,class _Ty1> 262 void _Dest_val(_Alloc& _Alval, _Ty1 *_Pdest) 263 { // destroy using allocator 264 _Alval.destroy(_Pdest); 265 } 266 _STD_END 267 268 #pragma pop_macro("new") 269 270 #pragma warning(pop) 271 #pragma pack(pop) 272 273 #endif /* RC_INVOKED */ 274 #endif /* _XMEMORY_ */
PtrBase
1 // TEMPLATE CLASS _Ptr_base 2 template<class _Ty> class _Ptr_base 3 { // base class for shared_ptr and weak_ptr 4 public: 5 typedef _Ptr_base<_Ty> _Myt; 6 typedef _Ty _Elem; 7 typedef _Elem element_type; 8 9 _Ptr_base(): _Ptr(0), _Rep(0) 10 { // construct 11 } 12 13 _Ptr_base(_Myt&& _Right): _Ptr(0), _Rep(0) 14 { // construct _Ptr_base object that takes resource from _Right 15 _Assign_rv(_STD forward<_Myt>(_Right)); 16 } 17 18 template<class _Ty2> _Ptr_base(_Ptr_base<_Ty2>&& _Right): _Ptr(_Right._Ptr), _Rep(_Right._Rep) 19 { // construct _Ptr_base object that takes resource from _Right 20 _Right._Ptr = 0; 21 _Right._Rep = 0; 22 } 23 24 _Myt& operator=(_Myt&& _Right) 25 { // construct _Ptr_base object that takes resource from _Right 26 _Assign_rv(_STD forward<_Myt>(_Right)); 27 return (*this); 28 } 29 30 void _Assign_rv(_Myt&& _Right) 31 { // assign by moving _Right 32 if (this != &_Right) 33 _Swap(_Right); 34 } 35 36 long use_count() const 37 { // return use count 38 return (_Rep ? _Rep->_Use_count() : 0); 39 } 40 41 void _Swap(_Ptr_base& _Right) 42 { // swap pointers 43 _STD swap(_Rep, _Right._Rep); 44 _STD swap(_Ptr, _Right._Ptr); 45 } 46 47 template<class _Ty2> 48 bool owner_before(const _Ptr_base<_Ty2>& _Right) const 49 { // compare addresses of manager objects 50 return (_Rep < _Right._Rep); 51 } 52 53 void *_Get_deleter(const _XSTD2 type_info& _Type) const 54 { // return pointer to deleter object if its type is _Type 55 return (_Rep ? _Rep->_Get_deleter(_Type) : 0); 56 } 57 58 _Ty *_Get() const 59 { // return pointer to resource 60 return (_Ptr); 61 } 62 63 bool _Expired() const 64 { // test if expired 65 return (!_Rep || _Rep->_Expired()); 66 } 67 68 void _Decref() 69 { // decrement reference count 70 if (_Rep != 0) 71 _Rep->_Decref(); 72 } 73 74 void _Reset() 75 { // release resource 76 _Reset(0, 0); 77 } 78 79 template<class _Ty2> 80 void _Reset(const _Ptr_base<_Ty2>& _Other) 81 { // release resource and take ownership of _Other._Ptr 82 _Reset(_Other._Ptr, _Other._Rep, false); 83 } 84 85 template<class _Ty2> 86 void _Reset(const _Ptr_base<_Ty2>& _Other, bool _Throw) 87 { // release resource and take ownership from weak_ptr _Other._Ptr 88 _Reset(_Other._Ptr, _Other._Rep, _Throw); 89 } 90 91 template<class _Ty2> 92 void _Reset(const _Ptr_base<_Ty2>& _Other, const _Static_tag&) 93 { // release resource and take ownership of _Other._Ptr 94 _Reset(static_cast<_Elem *>(_Other._Ptr), _Other._Rep); 95 } 96 97 template<class _Ty2> 98 void _Reset(const _Ptr_base<_Ty2>& _Other, const _Const_tag&) 99 { // release resource and take ownership of _Other._Ptr 100 _Reset(const_cast<_Elem *>(_Other._Ptr), _Other._Rep); 101 } 102 103 template<class _Ty2> 104 void _Reset(const _Ptr_base<_Ty2>& _Other, const _Dynamic_tag&) 105 { // release resource and take ownership of _Other._Ptr 106 _Elem *_Ptr = dynamic_cast<_Elem *>(_Other._Ptr); 107 if (_Ptr) 108 _Reset(_Ptr, _Other._Rep); 109 else 110 _Reset(); 111 } 112 template<class _Ty2> 113 void _Reset(auto_ptr<_Ty2>& _Other) 114 { // release resource and take _Other.get() 115 _Ty2 *_Px = _Other.get(); 116 _Reset0(_Px, new _Ref_count<_Elem>(_Px)); 117 _Other.release(); 118 _Enable_shared(_Px, _Rep); 119 } 120 void _Reset(_Ty *_Other_ptr, _Ref_count_base *_Other_rep) 121 { // release resource and take _Other_ptr through _Other_rep 122 if (_Other_rep) 123 _Other_rep->_Incref(); 124 _Reset0(_Other_ptr, _Other_rep); 125 } 126 void _Reset(_Ty *_Other_ptr, _Ref_count_base *_Other_rep, bool _Throw) 127 { // take _Other_ptr through _Other_rep from weak_ptr if not expired 128 // otherwise, leave in default state if !_Throw, 129 // otherwise throw exception 130 if (_Other_rep && _Other_rep->_Incref_nz()) 131 _Reset0(_Other_ptr, _Other_rep); 132 else if (_Throw) 133 _THROW_NCEE(bad_weak_ptr, 0); 134 } 135 void _Reset0(_Ty *_Other_ptr, _Ref_count_base *_Other_rep) 136 { // release resource and take new resource 137 if (_Rep != 0) 138 _Rep->_Decref(); 139 _Rep = _Other_rep; 140 _Ptr = _Other_ptr; 141 } 142 void _Decwref() 143 { // decrement weak reference count 144 if (_Rep != 0) 145 _Rep->_Decwref(); 146 } 147 void _Resetw() 148 { // release weak reference to resource 149 _Resetw((_Elem *)0, 0); 150 } 151 template<class _Ty2> 152 void _Resetw(const _Ptr_base<_Ty2>& _Other) 153 { // release weak reference to resource and take _Other._Ptr 154 _Resetw(_Other._Ptr, _Other._Rep); 155 } 156 template<class _Ty2> 157 void _Resetw(const _Ty2 *_Other_ptr, _Ref_count_base *_Other_rep) 158 { // point to _Other_ptr through _Other_rep 159 _Resetw(const_cast<_Ty2*>(_Other_ptr), _Other_rep); 160 } 161 template<class _Ty2> 162 void _Resetw(_Ty2 *_Other_ptr, _Ref_count_base *_Other_rep) 163 { // point to _Other_ptr through _Other_rep 164 if (_Other_rep) 165 _Other_rep->_Incwref(); 166 if (_Rep != 0) 167 _Rep->_Decwref(); 168 _Rep = _Other_rep; 169 _Ptr = _Other_ptr; 170 } 171 private: 172 _Ty *_Ptr; 173 _Ref_count_base *_Rep; 174 template<class _Ty0> friend class _Ptr_base; 175 };
SharedPtr
1 // TEMPLATE CLASS shared_ptr 2 template<class _Ty> class shared_ptr: public _Ptr_base<_Ty> 3 { // class for reference counted resource management 4 public: 5 typedef shared_ptr<_Ty> _Myt; 6 typedef _Ptr_base<_Ty> _Mybase; 7 8 shared_ptr() 9 { // construct empty shared_ptr object 10 } 11 template<class _Ux> 12 explicit shared_ptr(_Ux *_Px) 13 { // construct shared_ptr object that owns _Px 14 _Resetp(_Px); 15 } 16 template<class _Ux,class _Dx> 17 shared_ptr(_Ux *_Px, _Dx _Dt) 18 { // construct with _Px, deleter 19 _Resetp(_Px, _Dt); 20 } 21 shared_ptr(_STD nullptr_t) 22 { // construct with nullptr 23 _Resetp((_Ty *)0); 24 } 25 template<class _Dx> 26 shared_ptr(_STD nullptr_t, _Dx _Dt) 27 { // construct with nullptr, deleter 28 _Resetp((_Ty *)0, _Dt); 29 } 30 template<class _Dx,class _Alloc> 31 shared_ptr(_STD nullptr_t, _Dx _Dt, _Alloc _Ax) 32 { // construct with nullptr, deleter, allocator 33 _Resetp((_Ty *)0, _Dt, _Ax); 34 } 35 template<class _Ux,class _Dx,class _Alloc> 36 shared_ptr(_Ux *_Px, _Dx _Dt, _Alloc _Ax) 37 { // construct with _Px, deleter, allocator 38 _Resetp(_Px, _Dt, _Ax); 39 } 40 shared_ptr(const _Myt& _Other) 41 { // construct shared_ptr object that owns same resource as _Other 42 this->_Reset(_Other); 43 } 44 template<class _Ty2> 45 shared_ptr(const shared_ptr<_Ty2>& _Other,typename enable_if<is_convertible<_Ty2 *, _Ty *>::value, 46 void *>::type * = 0) 47 { // construct shared_ptr object that owns same resource as _Other 48 this->_Reset(_Other); 49 } 50 template<class _Ty2> 51 explicit shared_ptr(const weak_ptr<_Ty2>& _Other,bool _Throw = true) 52 { // construct shared_ptr object that owns resource *_Other 53 this->_Reset(_Other, _Throw); 54 } 55 template<class _Ty2> 56 shared_ptr(auto_ptr<_Ty2>& _Other) 57 { // construct shared_ptr object that owns *_Other.get() 58 this->_Reset(_Other); 59 } 60 template<class _Ty2> 61 shared_ptr(const shared_ptr<_Ty2>& _Other, const _Static_tag& _Tag) 62 { // construct shared_ptr object for static_pointer_cast 63 this->_Reset(_Other, _Tag); 64 } 65 template<class _Ty2> 66 shared_ptr(const shared_ptr<_Ty2>& _Other, const _Const_tag& _Tag) 67 { // construct shared_ptr object for const_pointer_cast 68 this->_Reset(_Other, _Tag); 69 } 70 template<class _Ty2> 71 shared_ptr(const shared_ptr<_Ty2>& _Other, const _Dynamic_tag& _Tag) 72 { // construct shared_ptr object for dynamic_pointer_cast 73 this->_Reset(_Other, _Tag); 74 } 75 shared_ptr(_Myt&& _Right): _Mybase(_STD forward<_Myt>(_Right)) 76 { // construct shared_ptr object that takes resource from _Right 77 } 78 template<class _Ty2> 79 shared_ptr(shared_ptr<_Ty2>&& _Right,typename enable_if<is_convertible<_Ty2 *, _Ty *>::value, 80 void *>::type * = 0): _Mybase(_STD forward<shared_ptr<_Ty2> >(_Right)) 81 { // construct shared_ptr object that takes resource from _Right 82 } 83 _Myt& operator=(_Myt&& _Right) 84 { // construct shared_ptr object that takes resource from _Right 85 shared_ptr(_STD move(_Right)).swap(*this); 86 return (*this); 87 } 88 template<class _Ty2> 89 _Myt& operator=(shared_ptr<_Ty2>&& _Right) 90 { // construct shared_ptr object that takes resource from _Right 91 shared_ptr(_STD move(_Right)).swap(*this); 92 return (*this); 93 } 94 void swap(_Myt&& _Right) 95 { // exchange contents with movable _Right 96 _Mybase::swap(_STD move(_Right)); 97 } 98 ~shared_ptr() 99 { // release resource 100 this->_Decref(); 101 } 102 _Myt& operator=(const _Myt& _Right) 103 { // assign shared ownership of resource owned by _Right 104 shared_ptr(_Right).swap(*this); 105 return (*this); 106 } 107 template<class _Ty2> 108 _Myt& operator=(const shared_ptr<_Ty2>& _Right) 109 { // assign shared ownership of resource owned by _Right 110 shared_ptr(_Right).swap(*this); 111 return (*this); 112 } 113 template<class _Ty2> 114 _Myt& operator=(auto_ptr<_Ty2>& _Right) 115 { // assign ownership of resource pointed to by _Right 116 shared_ptr(_Right).swap(*this); 117 return (*this); 118 } 119 void reset() 120 { // release resource and convert to empty shared_ptr object 121 shared_ptr().swap(*this); 122 } 123 template<class _Ux> 124 void reset(_Ux *_Px) 125 { // release, take ownership of _Px 126 shared_ptr(_Px).swap(*this); 127 } 128 template<class _Ux,class _Dx> 129 void reset(_Ux *_Px, _Dx _Dt) 130 { // release, take ownership of _Px, with deleter _Dt 131 shared_ptr(_Px, _Dt).swap(*this); 132 } 133 //#if _HAS_CPP0X 134 template<class _Ux, class _Dx, class _Alloc> 135 void reset(_Ux *_Px, _Dx _Dt, _Alloc _Ax) 136 { // release, take ownership of _Px, with deleter _Dt, allocator _Ax 137 shared_ptr(_Px, _Dt, _Ax).swap(*this); 138 } 139 //#endif /* _HAS_CPP0X */ 140 void swap(_Myt& _Other) 141 { // swap pointers 142 this->_Swap(_Other); 143 } 144 _Ty *get() const 145 { // return pointer to resource 146 return (this->_Get()); 147 } 148 typename tr1::add_reference<_Ty>::type operator*() const 149 { // return reference to resource 150 return (*this->_Get()); 151 } 152 _Ty *operator->() const 153 { // return pointer to resource 154 return (this->_Get()); 155 } 156 bool unique() const 157 { // return true if no other shared_ptr object owns this resource 158 return (this->use_count() == 1); 159 } 160 _OPERATOR_BOOL() const 161 { // test if shared_ptr object owns no resource 162 return (this->_Get() != 0 ? _CONVERTIBLE_TO_TRUE : 0); 163 } 164 private: 165 template<class _Ux> 166 void _Resetp(_Ux *_Px) 167 { // release, take ownership of _Px 168 _TRY_BEGIN // allocate control block and reset 169 _Resetp0(_Px, new _Ref_count<_Ux>(_Px)); 170 _CATCH_ALL // allocation failed, delete resource 171 delete _Px; 172 _RERAISE; 173 _CATCH_END 174 } 175 template<class _Ux,class _Dx> 176 void _Resetp(_Ux *_Px, _Dx _Dt) 177 { // release, take ownership of _Px, deleter _Dt 178 _TRY_BEGIN // allocate control block and reset 179 _Resetp0(_Px, new _Ref_count_del<_Ux, _Dx>(_Px, _Dt)); 180 _CATCH_ALL // allocation failed, delete resource 181 _Dt(_Px); 182 _RERAISE; 183 _CATCH_END 184 } 185 //#if _HAS_CPP0X 186 template<class _Ux,class _Dx,class _Alloc> 187 void _Resetp(_Ux *_Px, _Dx _Dt, _Alloc _Ax) 188 { // release, take ownership of _Px, deleter _Dt, allocator _Ax 189 typedef _Ref_count_del_alloc<_Ux, _Dx, _Alloc> _Refd; 190 typename _Alloc::template rebind<_Refd>::other _Al = _Ax; 191 192 _TRY_BEGIN // allocate control block and reset 193 _Refd *_Ptr = _Al.allocate(1); 194 new (_Ptr) _Refd(_Px, _Dt, _Al); 195 _Resetp0(_Px, _Ptr); 196 _CATCH_ALL // allocation failed, delete resource 197 _Dt(_Px); 198 _RERAISE; 199 _CATCH_END 200 } 201 //#endif /* _HAS_CPP0X */ 202 public: 203 template<class _Ux> 204 void _Resetp0(_Ux *_Px, _Ref_count_base *_Rx) 205 { // release resource and take ownership of _Px 206 this->_Reset0(_Px, _Rx); 207 _Enable_shared(_Px, _Rx); 208 } 209 }; 210 template<class _Ty1,class _Ty2> 211 bool operator==(const shared_ptr<_Ty1>& _S1,const shared_ptr<_Ty2>& _S2) 212 { // test if shared_ptr == shared_ptr 213 return (_S1.get() == _S2.get()); 214 } 215 template<class _Ty1,class _Ty2> 216 bool operator!=(const shared_ptr<_Ty1>& _S1,const shared_ptr<_Ty2>& _S2) 217 { // test if shared_ptr != shared_ptr 218 return (!(_S1 == _S2)); 219 } 220 template<class _Ty1,class _Ty2> 221 bool operator<(const shared_ptr<_Ty1>& _S1,const shared_ptr<_Ty2>& _S2) 222 { // test if shared_ptr < shared_ptr 223 return (_S1.get() < _S2.get()); 224 } 225 template<class _Ty1,class _Ty2> 226 bool operator>=(const shared_ptr<_Ty1>& _S1,const shared_ptr<_Ty2>& _S2) 227 { // shared_ptr >= shared_ptr 228 return (!(_S1 < _S2)); 229 } 230 template<class _Ty1,class _Ty2> 231 bool operator>(const shared_ptr<_Ty1>& _S1,const shared_ptr<_Ty2>& _S2) 232 { // test if shared_ptr > shared_ptr 233 return (_S2 < _S1); 234 } 235 template<class _Ty1,class _Ty2> 236 bool operator<=(const shared_ptr<_Ty1>& _S1,const shared_ptr<_Ty2>& _S2) 237 { // test if shared_ptr <= shared_ptr 238 return (!(_S2 < _S1)); 239 } 240 template<class _Elem,class _Traits,class _Ty> 241 basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Out,const shared_ptr<_Ty>& _Px) 242 { // write contained pointer to stream 243 return (_Out << _Px.get()); 244 } 245 template<class _Ty> 246 void swap(shared_ptr<_Ty>& _Left,shared_ptr<_Ty>& _Right) 247 { // swap _Left and _Right shared_ptrs 248 _Left.swap(_Right); 249 } 250 template<class _Ty> 251 void swap(shared_ptr<_Ty>& _Left,shared_ptr<_Ty>&& _Right) 252 { // swap _Left and _Right shared_ptrs 253 _Left.swap(_Right); 254 } 255 template<class _Ty> 256 void swap(shared_ptr<_Ty>&& _Left,shared_ptr<_Ty>& _Right) 257 { // swap _Left and _Right shared_ptrs 258 _Right.swap(_Left); 259 } 260 template<class _Ty1,class _Ty2> 261 shared_ptr<_Ty1> static_pointer_cast(const shared_ptr<_Ty2>& _Other) 262 { // return shared_ptr object holding static_cast<_Ty1 *>(_Other.get()) 263 return (shared_ptr<_Ty1>(_Other, _Static_tag())); 264 } 265 template<class _Ty1,class _Ty2> 266 shared_ptr<_Ty1> const_pointer_cast(const shared_ptr<_Ty2>& _Other) 267 { // return shared_ptr object holding const_cast<_Ty1 *>(_Other.get()) 268 return (shared_ptr<_Ty1>(_Other, _Const_tag())); 269 } 270 template<class _Ty1,class _Ty2> 271 shared_ptr<_Ty1> dynamic_pointer_cast(const shared_ptr<_Ty2>& _Other) 272 { // return shared_ptr object holding dynamic_cast<_Ty1 *>(_Other.get()) 273 return (shared_ptr<_Ty1>(_Other, _Dynamic_tag())); 274 } 275 template<class _Dx,class _Ty> 276 _Dx *get_deleter(const shared_ptr<_Ty>& _Sx) 277 { // return pointer to shared_ptr's deleter object if its type is _Ty 278 return ((_Dx *)_Sx._Get_deleter(typeid(_Dx))); 279 } 280 281 #if _HAS_CPP0X 282 283 // TEMPLATE CLASS _Ref_count_obj 284 template<class _Ty> 285 class _Ref_count_obj: public _Ref_count_base 286 { // handle reference counting for object in control block, no allocator 287 public: 288 #define _REF_COUNT_OBJ_CTOR 289 #define _INCL_FILE_xxshared 290 #include <xfwrap> 291 #undef _REF_COUNT_OBJ_CTOR 292 _Ty *_Getptr() const 293 { // get pointer 294 return ((_Ty *)&_Storage); 295 } 296 private: 297 virtual void _Destroy() 298 { // destroy managed resource 299 _Getptr()->~_Ty(); 300 } 301 virtual void _Delete_this() 302 { // destroy self 303 delete this; 304 } 305 typename aligned_storage<sizeof(_Ty),alignment_of<_Ty>::value>::type _Storage; 306 }; 307 // TEMPLATE CLASS _Ref_count_obj_alloc 308 template<class _Ty,class _Alloc> 309 class _Ref_count_obj_alloc: public _Ref_count_base 310 { // handle reference counting for object in control block, allocator 311 public: 312 typedef _Ref_count_obj_alloc<_Ty, _Alloc> _Myty; 313 typedef typename _Alloc::template rebind<_Myty>::other _Myalty; 314 315 #define _REF_COUNT_OBJ_ALLOC_CTOR 316 #define _INCL_FILE_xxshared 317 #include <xfwrap> 318 #undef _REF_COUNT_OBJ_ALLOC_CTOR 319 320 _Ty *_Getptr() const 321 { // get pointer 322 return ((_Ty *)&_Storage); 323 } 324 325 private: 326 virtual void _Destroy() 327 { // destroy managed resource 328 _Getptr()->~_Ty(); 329 } 330 virtual void _Delete_this() 331 { // destroy self 332 _Myalty _Al = _Myal; 333 _Dest_val(_Al, this); 334 _Al.deallocate(this, 1); 335 } 336 typename aligned_storage<sizeof (_Ty),alignment_of<_Ty>::value>::type _Storage; 337 _Myalty _Myal; // the stored allocator for this 338 };