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.

  1. 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.
  2. You should make sure that you understand how templates work with C++ before you use the STL. 
  3. Templates = replacement = code expansion at compiling-time.
  4. 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.
  5. The STL also includes a large collection of algorithms that manipulate the data stored in containers.
  6. 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.
  7. reverse( objectOfcontainer.begin(), objectOfcontainer.end())
  8. 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.
  9. 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.
  10. 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.
  11. 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.
  12. Concept programming, Generic programming 

Classification of STL components

  1. The STL components are divided into six broad categories on the basis of functionality: Containers, Iterator, Algorithms, Function Objects, Utilities, and Allocator.
  2. 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.
  3. 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;
  4.   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)
    View Code

     

 Container-->Concepts-->General concepts-->Container

  1. 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.
  2. 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.
  3. 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); 
  4.  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

  1. 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).
  2. Complexity Guarantees: The equality and inequality operations are linear in the container’s size.
  3. 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.
  4. Must support functions: EqualityComparable, LessThanComparable.

Container-->Concepts-->General concepts-->Reversible Container

  1. A reversible container is a forward container whose iterators are bidirectional iterators. It allows backwards iteration through the container.
  2. 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.
  3. 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--.
  4.  X::const_reverse_iterator: A Reverse Iterator adaptor whose base iterator type is the container’s const iterator type.
  5. a.rbegin() == X::reverse_iterator (a.end() ); a.rend() == X::reverse_iterator (a.begin() );

Container-->Concepts-->General concepts-->Random Access Container

  1. 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.
  2. 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.
  3. 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

  1. A sequence is a variable-sized Container whose elements are arranged in a strict linear order. It supports insertion and removal of elements.
  2. Forward Container; Default Constructible
  3. The fill constructor, default constructor and range constructor are linear
  4. Front is amortized constant time.
  5. Fill insert, range insert, and range erase are linear.
  6. The complexities of single-element insert and erase are sequence dependent.
  7. Models: vector; deque; list; slist
  8. 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.
  9. 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.
  10. 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.
  11. 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

  1. 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.
  2. Front, push front, and pop front are amortized constant time.
  3. Models: list; deque
  4. 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.
  5. 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

  1. 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.
  2. Back, push back, and pop back are amortized constant time.
  3. Models: vector, list, deque
  4. 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

  1. 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.
  2. 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. 
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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.
  9. Models: set; multiset; hash_set; hash_multiset; map; multimap; hash_map; hash_multimap
  10. Red-Black Tree:http://en.wikipedia.org/wiki/Red%E2%80%93black_tree
  11.    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
    View Code

    二叉树的意思是:任何节点最多只能有两个子节点的树。二叉搜索树可提供log(N)的元素插入和访问,它的节点旋转规则是:任何节点的键值一定大于其左子节点树中的每个节点的键值,并小于其右子树中的每个节点的键值。因此,从树节点一直往左走到底,即得最小元素;从根节点一直往右走到底,却得最大元素。但是,由于插入值无规律,二叉搜索树可能失去平衡,造成搜索效率低落的情况。解决办法就是尽量使树形左右“平衡”,对于何为“平衡”,没有一个绝对的定义,大致的意思就是“没有一个节点过深”。常见的平衡二叉树有AVL-tree, RB-tree, AA-tree,它们都比上面说的一般二叉树复杂,插入节点和删除节点时要做一些额外操作来维护树形平衡,但是它们可以避免极难应付的极不平衡的情况,而且由于它们总是保持某种程度的平衡,所以元素访问时间平均而言就比较少。

SGI STL实现的搜索树是RB-tree,它在一般二叉树的基础上增加了以下必须满足的条件:

  • 每个节点不是红色就是黑色;
  • 根节点为黑色;
  • 如果节点为红,其子节点必须为黑,如果节点为黑,则随意;
  • 任一节点到树尾端的任何路径(比如从根节点到任意一个叶节点),所含的黑节点数量必须相同。

根据规则4,新增节点必须为红色;根据规则3,新增节点的父节点必须为黑。当新节点根据一般二叉树搜索规则到达其插入点,却未能符合上述条件时,就必须调整节点颜色和旋转树形。注意经过调整后,叶节点可能为黑色。

Associative Container->Simple Associative Container

  1. 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.
  2. Immutability of element: Every element of a Simple Associative Container is immutable. Objects may be inserted and erased, but not modified.
  3. Models: set; multiset; hash_set; hash_multiset;
  4. 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.
  5. 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> 
  6. 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.
  7.   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 };
    View Code
      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 } 
    View Code

     

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
View Code

 

 

  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 */
View Code

 

  1. 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>.
  2. Models: map; multimap; hash_map; hash_multimap
  3. 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.
  4. Key type: X::key_type The type of the key associated with X::value_type.
  5. 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.
  6. 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

  1. 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.)
  2. 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)
  3. Two new types are introduced, in addition to the types defined in the Associative Container and Reversible Container requirements.
  4.  X::key_compare The type of a Strict Weak Ordering used to compare keys. Its argument type must be X::key_type.
  5.  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.
  6. 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.
  7. 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).
  8. 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.
  9. Models: set; multiset; map; multimap
  10. 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.
  11. 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

  1. 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.
  2. Hash function X::hasher A type that is a model of Hash Function X::hasher’s argument type must be X::key_type.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. The default constructor, constructor with bucket count, constructor with hash function, and constructor with key equal, are all amortized constant time.
  8. Hash Function and Key Equal are amortized constant time.
  9. Average complexity for Erase key is O(count(k). Worst case is linear in the size of the container.
  10. 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.
  11. 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.
  12. Models: hash_set; hash_map; hash_multiset; hash_multimap.
  13. 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.
  14. 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

  1. 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.
  2. 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*
  3. 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.
  4. 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).
  5. 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.
  6. 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

  1. 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.
  2. 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.
  3. The name deque is pronounced “deck”, and stands for “double-ended queue.”
  4. 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.
  5. 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.
  6. 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>

  1. 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.
  2. 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.
  3. 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.
  4. 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. 
  5. A vector<T>::iterator will be invalidated if an insertion requires a reallocation. 
  6. 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.
  7. A list is exactly the opposite: iterators predecessor/successor relationship is not invariant.
  8. 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.
  9. 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.
  10. 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>

  1. 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.
  2. 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.
  3. 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.
  4. Key: The set’s key type and value type. This is also defined as set::key_type and set::value_type.
  5. 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.
  6. Alloc: The set’s allocator, used for all internal memory management.

Associative Container-->map<Key,Data, Compare, Alloc>

  1. 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.
  2. 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.
  3. 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; }};
  4. 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.
  5. 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().
  6. 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.
  7. 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
View Code

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_ */
View Code

 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 };
View Code

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 };
View Code

 

posted @ 2013-08-15 15:35  iDragon  阅读(613)  评论(0编辑  收藏  举报