📄 stl_deque.h
字号:
/* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * * Copyright (c) 1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. *//* NOTE: This is an internal header file, included by other STL headers. * You should not attempt to use it directly. */#ifndef __SGI_STL_INTERNAL_DEQUE_H#define __SGI_STL_INTERNAL_DEQUE_H/* Class invariants: * For any nonsingular iterator i: * i.node is the address of an element in the map array. The * contents of i.node is a pointer to the beginning of a node. * i.first == *(i.node) * i.last == i.first + node_size * i.cur is a pointer in the range [i.first, i.last). NOTE: * the implication of this is that i.cur is always a dereferenceable * pointer, even if i is a past-the-end iterator. * Start and Finish are always nonsingular iterators. NOTE: this means * that an empty deque must have one node, and that a deque * with N elements, where N is the buffer size, must have two nodes. * For every node other than start.node and finish.node, every element * in the node is an initialized object. If start.node == finish.node, * then [start.cur, finish.cur) are initialized objects, and * the elements outside that range are uninitialized storage. Otherwise, * [start.cur, start.last) and [finish.first, finish.cur) are initialized * objects, and [start.first, start.cur) and [finish.cur, finish.last) * are uninitialized storage. * [map, map + map_size) is a valid, non-empty range. * [start.node, finish.node] is a valid range contained within * [map, map + map_size). * A pointer in the range [map, map + map_size) points to an allocated * node if and only if the pointer is in the range [start.node, finish.node]. *//* * In previous versions of deque, node_size was fixed by the * implementation. In this version, however, users can select * the node size. Deque has three template parameters; the third, * a number of type size_t, is the number of elements per node. * If the third template parameter is 0 (which is the default), * then deque will use a default node size. * * The only reason for using an alternate node size is if your application * requires a different performance tradeoff than the default. If, * for example, your program contains many deques each of which contains * only a few elements, then you might want to save memory (possibly * by sacrificing some speed) by using smaller nodes. * * Unfortunately, some compilers have trouble with non-type template * parameters; stl_config.h defines __STL_NON_TYPE_TMPL_PARAM_BUG if * that is the case. If your compiler is one of them, then you will * not be able to use alternate node sizes; you will have to use the * default value. */__STL_BEGIN_NAMESPACE #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)#pragma set woff 1174#endif// Note: this function is simply a kludge to work around several compilers'// bugs in handling constant expressions.inline size_t __deque_buf_size(size_t n, size_t sz){ return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));}#ifndef __STL_NON_TYPE_TMPL_PARAM_BUGtemplate <class T, class Ref, class Ptr, size_t BufSiz>struct __deque_iterator { typedef __deque_iterator<T, T&, T*, BufSiz> iterator; typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator; static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); }#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */template <class T, class Ref, class Ptr>struct __deque_iterator { typedef __deque_iterator<T, T&, T*> iterator; typedef __deque_iterator<T, const T&, const T*> const_iterator; static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }#endif typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef Ptr pointer; typedef Ref reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T** map_pointer; typedef __deque_iterator self; T* cur; T* first; T* last; map_pointer node; __deque_iterator(T* x, map_pointer y) : cur(x), first(*y), last(*y + buffer_size()), node(y) {} __deque_iterator() : cur(0), first(0), last(0), node(0) {} __deque_iterator(const iterator& x) : cur(x.cur), first(x.first), last(x.last), node(x.node) {} reference operator*() const { return *cur; }#ifndef __SGI_STL_NO_ARROW_OPERATOR pointer operator->() const { return &(operator*()); }#endif /* __SGI_STL_NO_ARROW_OPERATOR */ difference_type operator-(const self& x) const { return difference_type(buffer_size()) * (node - x.node - 1) + (cur - first) + (x.last - x.cur); } self& operator++() { ++cur; if (cur == last) { set_node(node + 1); cur = first; } return *this; } self operator++(int) { self tmp = *this; ++*this; return tmp; } self& operator--() { if (cur == first) { set_node(node - 1); cur = last; } --cur; return *this; } self operator--(int) { self tmp = *this; --*this; return tmp; } self& operator+=(difference_type n) { difference_type offset = n + (cur - first); if (offset >= 0 && offset < difference_type(buffer_size())) cur += n; else { difference_type node_offset = offset > 0 ? offset / difference_type(buffer_size()) : -difference_type((-offset - 1) / buffer_size()) - 1; set_node(node + node_offset); cur = first + (offset - node_offset * difference_type(buffer_size())); } return *this; } self operator+(difference_type n) const { self tmp = *this; return tmp += n; } self& operator-=(difference_type n) { return *this += -n; } self operator-(difference_type n) const { self tmp = *this; return tmp -= n; } reference operator[](difference_type n) const { return *(*this + n); } bool operator==(const self& x) const { return cur == x.cur; } bool operator!=(const self& x) const { return !(*this == x); } bool operator<(const self& x) const { return (node == x.node) ? (cur < x.cur) : (node < x.node); } void set_node(map_pointer new_node) { node = new_node; first = *new_node; last = first + difference_type(buffer_size()); }};#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION#ifndef __STL_NON_TYPE_TMPL_PARAM_BUGtemplate <class T, class Ref, class Ptr, size_t BufSiz>inline random_access_iterator_tagiterator_category(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { return random_access_iterator_tag();}template <class T, class Ref, class Ptr, size_t BufSiz>inline T* value_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { return 0;}template <class T, class Ref, class Ptr, size_t BufSiz>inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { return 0;}#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */template <class T, class Ref, class Ptr>inline random_access_iterator_tagiterator_category(const __deque_iterator<T, Ref, Ptr>&) { return random_access_iterator_tag();}template <class T, class Ref, class Ptr>inline T* value_type(const __deque_iterator<T, Ref, Ptr>&) { return 0; }template <class T, class Ref, class Ptr>inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr>&) { return 0;}#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */// See __deque_buf_size(). The only reason that the default value is 0// is as a workaround for bugs in the way that some compilers handle// constant expressions.template <class T, class Alloc = alloc, size_t BufSiz = 0> class deque {public: // Basic types typedef T value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type;public: // Iterators#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG typedef __deque_iterator<T, T&, T*, BufSiz> iterator; typedef __deque_iterator<T, const T&, const T&, BufSiz> const_iterator;#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ typedef __deque_iterator<T, T&, T*> iterator; typedef __deque_iterator<T, const T&, const T*> const_iterator;#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION typedef reverse_iterator<const_iterator> const_reverse_iterator; typedef reverse_iterator<iterator> reverse_iterator;#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ typedef reverse_iterator<const_iterator, value_type, const_reference, difference_type> const_reverse_iterator; typedef reverse_iterator<iterator, value_type, reference, difference_type> reverse_iterator; #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */protected: // Internal typedefs typedef pointer* map_pointer; typedef simple_alloc<value_type, Alloc> data_allocator; typedef simple_alloc<pointer, Alloc> map_allocator; static size_type buffer_size() { return __deque_buf_size(BufSiz, sizeof(value_type)); } static size_type initial_map_size() { return 8; }protected: // Data members iterator start; iterator finish; map_pointer map; size_type map_size;public: // Basic accessors iterator begin() { return start; } iterator end() { return finish; } const_iterator begin() const { return start; } const_iterator end() const { return finish; } reverse_iterator rbegin() { return reverse_iterator(finish); } reverse_iterator rend() { return reverse_iterator(start); } const_reverse_iterator rbegin() const { return const_reverse_iterator(finish); } const_reverse_iterator rend() const { return const_reverse_iterator(start); } reference operator[](size_type n) { return start[difference_type(n)]; } const_reference operator[](size_type n) const { return start[difference_type(n)]; } reference front() { return *start; } reference back() { iterator tmp = finish; --tmp; return *tmp; } const_reference front() const { return *start; } const_reference back() const { const_iterator tmp = finish; --tmp; return *tmp; } size_type size() const { return finish - start;; } size_type max_size() const { return size_type(-1); } bool empty() const { return finish == start; }public: // Constructor, destructor. deque() : start(), finish(), map(0), map_size(0) { create_map_and_nodes(0); } deque(const deque& x) : start(), finish(), map(0), map_size(0) { create_map_and_nodes(x.size()); __STL_TRY { uninitialized_copy(x.begin(), x.end(), start); } __STL_UNWIND(destroy_map_and_nodes()); } deque(size_type n, const value_type& value) : start(), finish(), map(0), map_size(0) { fill_initialize(n, value); } deque(int n, const value_type& value) : start(), finish(), map(0), map_size(0) { fill_initialize(n, value); } deque(long n, const value_type& value) : start(), finish(), map(0), map_size(0) { fill_initialize(n, value); } explicit deque(size_type n) : start(), finish(), map(0), map_size(0) { fill_initialize(n, value_type()); }#ifdef __STL_MEMBER_TEMPLATES template <class InputIterator> deque(InputIterator first, InputIterator last) : start(), finish(), map(0), map_size(0) { range_initialize(first, last, iterator_category(first)); }#else /* __STL_MEMBER_TEMPLATES */ deque(const value_type* first, const value_type* last) : start(), finish(), map(0), map_size(0) { create_map_and_nodes(last - first); __STL_TRY { uninitialized_copy(first, last, start); } __STL_UNWIND(destroy_map_and_nodes()); } deque(const_iterator first, const_iterator last) : start(), finish(), map(0), map_size(0) { create_map_and_nodes(last - first); __STL_TRY { uninitialized_copy(first, last, start); } __STL_UNWIND(destroy_map_and_nodes()); }#endif /* __STL_MEMBER_TEMPLATES */ ~deque() { destroy(start, finish); destroy_map_and_nodes(); } deque& operator= (const deque& x) { const size_type len = size(); if (&x != this) { if (len >= x.size()) erase(copy(x.begin(), x.end(), start), finish); else { const_iterator mid = x.begin() + difference_type(len); copy(x.begin(), mid, start); insert(finish, mid, x.end()); } } return *this; } void swap(deque& x) { __STD::swap(start, x.start); __STD::swap(finish, x.finish); __STD::swap(map, x.map); __STD::swap(map_size, x.map_size); }public: // push_* and pop_* void push_back(const value_type& t) { if (finish.cur != finish.last - 1) { construct(finish.cur, t); ++finish.cur; } else push_back_aux(t); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -