deque.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,512 行 · 第 1/4 页
HPP
1,512 行
/* * * 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) 1996 * 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. * */////////////////////////////////////////////////////////////////////////////////// (C) Copyright Ion Gaztanaga 2005-2006. Distributed under the Boost// Software License, Version 1.0. (See accompanying file// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//// See http://www.boost.org/libs/interprocess for documentation.//////////////////////////////////////////////////////////////////////////////////// This file comes from SGI's stl_deque.h and stl_uninitialized.h files. // Modified by Ion Gaztanaga 2005.// Renaming, isolating and porting to generic algorithms. Pointer typedef // set to allocator::pointer to allow placing it in shared memory./////////////////////////////////////////////////////////////////////////////////#ifndef BOOST_INTERPROCESS_DEQUE_HPP#define BOOST_INTERPROCESS_DEQUE_HPP#if (defined _MSC_VER) && (_MSC_VER >= 1200)# pragma once#endif#include <boost/interprocess/detail/config_begin.hpp>#include <boost/interprocess/detail/workaround.hpp>#include <boost/interprocess/detail/utilities.hpp>#include <boost/interprocess/detail/iterators.hpp>#include <boost/interprocess/detail/algorithms.hpp>#include <boost/interprocess/detail/min_max.hpp>#include <boost/interprocess/detail/mpl.hpp>#include <boost/interprocess/interprocess_fwd.hpp>#include <cstddef>#include <iterator>#include <cassert>#include <memory>#include <algorithm>#include <stdexcept>#include <boost/detail/no_exceptions_support.hpp>#include <boost/type_traits/has_trivial_destructor.hpp>#include <boost/type_traits/has_trivial_copy.hpp>#include <boost/type_traits/has_trivial_assign.hpp>#include <boost/type_traits/has_nothrow_copy.hpp>#include <boost/type_traits/has_nothrow_assign.hpp>#include <boost/interprocess/detail/move_iterator.hpp>#include <boost/interprocess/detail/move.hpp>#include <boost/interprocess/detail/advanced_insert_int.hpp>namespace boost {namespace interprocess {/// @condtemplate <class T, class Alloc>class deque;template <class T, class A>struct deque_value_traits{ typedef T value_type; typedef A allocator_type; static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value; static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<value_type>::value || trivial_dctr; static const bool trivial_copy = has_trivial_copy<value_type>::value; static const bool nothrow_copy = has_nothrow_copy<value_type>::value; static const bool trivial_assign = has_trivial_assign<value_type>::value; static const bool nothrow_assign = has_nothrow_assign<value_type>::value;};// Note: this function is simply a kludge to work around several compilers'// bugs in handling constant expressions.inline std::size_t deque_buf_size(std::size_t size) { return size < 512 ? std::size_t(512 / size) : std::size_t(1); }// Deque base class. It has two purposes. First, its constructor// and destructor allocate (but don't initialize) storage. This makes// exception safety easier.template <class T, class Alloc>class deque_base{ public: typedef typename Alloc::value_type val_alloc_val; typedef typename Alloc::pointer val_alloc_ptr; typedef typename Alloc::const_pointer val_alloc_cptr; typedef typename Alloc::reference val_alloc_ref; typedef typename Alloc::const_reference val_alloc_cref; typedef typename Alloc::value_type val_alloc_diff; typedef typename Alloc::template rebind <typename Alloc::pointer>::other ptr_alloc_t; typedef typename ptr_alloc_t::value_type ptr_alloc_val; typedef typename ptr_alloc_t::pointer ptr_alloc_ptr; typedef typename ptr_alloc_t::const_pointer ptr_alloc_cptr; typedef typename ptr_alloc_t::reference ptr_alloc_ref; typedef typename ptr_alloc_t::const_reference ptr_alloc_cref; typedef typename Alloc::template rebind<T>::other allocator_type; typedef allocator_type stored_allocator_type; protected: typedef deque_value_traits<T, Alloc> traits_t; typedef typename Alloc::template rebind<typename Alloc::pointer>::other map_allocator_type; static std::size_t s_buffer_size() { return deque_buf_size(sizeof(T)); } val_alloc_ptr priv_allocate_node() { return this->alloc().allocate(s_buffer_size()); } void priv_deallocate_node(val_alloc_ptr p) { this->alloc().deallocate(p, s_buffer_size()); } ptr_alloc_ptr priv_allocate_map(std::size_t n) { return this->ptr_alloc().allocate(n); } void priv_deallocate_map(ptr_alloc_ptr p, std::size_t n) { this->ptr_alloc().deallocate(p, n); } public: // 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]. class const_iterator : public std::iterator<std::random_access_iterator_tag, val_alloc_val, val_alloc_diff, val_alloc_cptr, val_alloc_cref> { public: static std::size_t s_buffer_size() { return deque_base<T, Alloc>::s_buffer_size(); } typedef std::random_access_iterator_tag iterator_category; typedef val_alloc_val value_type; typedef val_alloc_cptr pointer; typedef val_alloc_cref reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef ptr_alloc_ptr index_pointer; typedef const_iterator self_t; friend class deque<T, Alloc>; friend class deque_base<T, Alloc>; protected: val_alloc_ptr m_cur; val_alloc_ptr m_first; val_alloc_ptr m_last; index_pointer m_node; public: const_iterator(val_alloc_ptr x, index_pointer y) : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y) {} const_iterator() : m_cur(0), m_first(0), m_last(0), m_node(0) {} const_iterator(const const_iterator& x) : m_cur(x.m_cur), m_first(x.m_first), m_last(x.m_last), m_node(x.m_node) {} reference operator*() const { return *this->m_cur; } pointer operator->() const { return this->m_cur; } difference_type operator-(const self_t& x) const { return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) + (this->m_cur - this->m_first) + (x.m_last - x.m_cur); } self_t& operator++() { ++this->m_cur; if (this->m_cur == this->m_last) { this->priv_set_node(this->m_node + 1); this->m_cur = this->m_first; } return *this; } self_t operator++(int) { self_t tmp = *this; ++*this; return tmp; } self_t& operator--() { if (this->m_cur == this->m_first) { this->priv_set_node(this->m_node - 1); this->m_cur = this->m_last; } --this->m_cur; return *this; } self_t operator--(int) { self_t tmp = *this; --*this; return tmp; } self_t& operator+=(difference_type n) { difference_type offset = n + (this->m_cur - this->m_first); if (offset >= 0 && offset < difference_type(this->s_buffer_size())) this->m_cur += n; else { difference_type node_offset = offset > 0 ? offset / difference_type(this->s_buffer_size()) : -difference_type((-offset - 1) / this->s_buffer_size()) - 1; this->priv_set_node(this->m_node + node_offset); this->m_cur = this->m_first + (offset - node_offset * difference_type(this->s_buffer_size())); } return *this; } self_t operator+(difference_type n) const { self_t tmp = *this; return tmp += n; } self_t& operator-=(difference_type n) { return *this += -n; } self_t operator-(difference_type n) const { self_t tmp = *this; return tmp -= n; } reference operator[](difference_type n) const { return *(*this + n); } bool operator==(const self_t& x) const { return this->m_cur == x.m_cur; } bool operator!=(const self_t& x) const { return !(*this == x); } bool operator<(const self_t& x) const { return (this->m_node == x.m_node) ? (this->m_cur < x.m_cur) : (this->m_node < x.m_node); } bool operator>(const self_t& x) const { return x < *this; } bool operator<=(const self_t& x) const { return !(x < *this); } bool operator>=(const self_t& x) const { return !(*this < x); } void priv_set_node(index_pointer new_node) { this->m_node = new_node; this->m_first = *new_node; this->m_last = this->m_first + difference_type(this->s_buffer_size()); } friend const_iterator operator+(std::ptrdiff_t n, const const_iterator& x) { return x + n; } }; //Deque iterator class iterator : public const_iterator { public: typedef std::random_access_iterator_tag iterator_category; typedef val_alloc_val value_type; typedef val_alloc_ptr pointer; typedef val_alloc_ref reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef ptr_alloc_ptr index_pointer; typedef const_iterator self_t; friend class deque<T, Alloc>; friend class deque_base<T, Alloc>; private: explicit iterator(const const_iterator& x) : const_iterator(x){} public: //Constructors iterator(val_alloc_ptr x, index_pointer y) : const_iterator(x, y){} iterator() : const_iterator(){} //iterator(const const_iterator &cit) : const_iterator(cit){} iterator(const iterator& x) : const_iterator(x){} //Pointer like operators reference operator*() const { return *this->m_cur; } pointer operator->() const { return this->m_cur; } reference operator[](difference_type n) const { return *(*this + n); } //Increment / Decrement iterator& operator++() { this->const_iterator::operator++(); return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } iterator& operator--() { this->const_iterator::operator--(); return *this; } iterator operator--(int) { iterator tmp = *this; --*this; return tmp; } // Arithmetic iterator& operator+=(difference_type off) { this->const_iterator::operator+=(off); return *this; } iterator operator+(difference_type off) const { return iterator(this->const_iterator::operator+(off)); } friend iterator operator+(difference_type off, const iterator& right) { return iterator(off+static_cast<const const_iterator &>(right)); } iterator& operator-=(difference_type off) { this->const_iterator::operator-=(off); return *this; } iterator operator-(difference_type off) const { return iterator(this->const_iterator::operator-(off)); } difference_type operator-(const const_iterator& right) const { return static_cast<const const_iterator&>(*this) - right; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?