⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auto_buffer.hpp

📁 新版本TR1的stl
💻 HPP
📖 第 1 页 / 共 4 页
字号:
template<   ss_typename_param_k T
# ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
        ,   ss_typename_param_k A = ss_typename_type_def_k allocator_selector<T>::allocator_type
# else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
        ,   ss_typename_param_k A
# endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
# ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT
#  if defined(STLSOFT_COMPILER_IS_BORLAND)
        ,   ss_size_t           space   =   256
#  elif defined(STLSOFT_COMPILER_IS_DMC)
        ,   ss_size_t           SPACE   =   256
#  else /* ? compiler */
        ,   ss_size_t           SPACE   =   auto_buffer_internal_size_calculator<T>::value
#  endif /* compiler */
# else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
#  if !defined(STLSOFT_COMPILER_IS_BORLAND)
        ,   ss_size_t           SPACE   /* =   auto_buffer_internal_size_calculator<T>::value */
#  else /* ? compiler */
        ,   ss_size_t           space   /* =   256 */
#  endif /* compiler */
# endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
        >

 // End of pre-1.9 template parameter list
 // //////////////////////////////////////////////

#else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */

 // //////////////////////////////////////////////
 // This is the 1.9+ template parameter list

# ifndef STLSOFT_AUTO_BUFFER_NEW_FORM
#  define STLSOFT_AUTO_BUFFER_NEW_FORM
# endif /* !STLSOFT_AUTO_BUFFER_NEW_FORM */

template<   ss_typename_param_k T
# ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT
#  if defined(STLSOFT_COMPILER_IS_BORLAND)
        ,   ss_size_t           space   =   256
#  elif defined(STLSOFT_COMPILER_IS_DMC)
        ,   ss_size_t           SPACE   =   256
#  else /* ? compiler */
        ,   ss_size_t           SPACE   =   auto_buffer_internal_size_calculator<T>::value
#  endif /* compiler */
# else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
#  if !defined(STLSOFT_COMPILER_IS_BORLAND)
        ,   ss_size_t           SPACE   /* =   auto_buffer_internal_size_calculator<T>::value */
#  else /* ? compiler */
        ,   ss_size_t           space   /* =   256 */
#  endif /* compiler */
# endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
# ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
        ,   ss_typename_param_k A = ss_typename_type_def_k allocator_selector<T>::allocator_type
# else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
        ,   ss_typename_param_k A
# endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
        >

 // End of 1.9+ template parameter list
 // //////////////////////////////////////////////

#endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */

class auto_buffer
#if !defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE)
    : protected A
    , public stl_collection_tag
#else /* ? STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
    : public stl_collection_tag
#endif /* !STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
{
/// \name Member Types
/// @{
public:
    /// The value type
    typedef T                                                   value_type;
    /// The allocator type
    typedef A                                                   allocator_type;
#if !defined(STLSOFT_COMPILER_IS_BORLAND)
    enum
    {
        /// The number of items in the internal buffer
        space = SPACE
    };
#endif /* compiler */
    /// The type of the current parameterisation
#ifdef STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
    typedef auto_buffer<T, A, space>                            class_type;
#else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
    typedef auto_buffer<T, space, A>                            class_type;
#endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
    /// The reference type
    typedef ss_typename_type_k allocator_type::reference        reference;
    /// The non-mutable (const) reference type
    typedef ss_typename_type_k allocator_type::const_reference  const_reference;
    /// The pointer type
    typedef ss_typename_type_k allocator_type::pointer          pointer;
    /// The non-mutable (const) pointer type
    typedef ss_typename_type_k allocator_type::const_pointer    const_pointer;
    /// The size type
    typedef ss_size_t                                           size_type;
    /// The difference type
    typedef ss_ptrdiff_t                                        difference_type;
#if !defined(STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
    /// The iterator type
    typedef value_type                                          *iterator;
    /// The non-mutable (const) iterator type
    typedef value_type const                                    *const_iterator;
#else /* ? !STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
    /// The iterator type
    typedef
# if !defined(STLSOFT_COMPILER_IS_BORLAND)
           ss_typename_type_k
# endif /* compiler */
                       pointer_iterator <   value_type
                                        ,   pointer
                                        ,   reference
                                        >::type             iterator;
    /// The non-mutating (const) iterator type
    typedef
# if !defined(STLSOFT_COMPILER_IS_BORLAND)
         ss_typename_type_k
# endif /* compiler */
                       pointer_iterator <   value_type const
                                        ,   const_pointer
                                        ,   const_reference
                                        >::type             const_iterator;

    /// The mutating (non-const) reverse iterator type
    typedef reverse_iterator_base       <   iterator
                                        ,   value_type
                                        ,   reference
                                        ,   pointer
                                        ,   difference_type
                                        >                   reverse_iterator;

    /// The non-mutating (const) reverse iterator type
    typedef const_reverse_iterator_base <   const_iterator
                                        ,   value_type const
                                        ,   const_reference
                                        ,   const_pointer
                                        ,   difference_type
                                        >                   const_reverse_iterator;
#endif /* !STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
/// @}

/// \name Implementation
/// @{
private:
    pointer allocate_(size_type cItems, void const* hint)
    {
#ifdef STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT
        return get_allocator().allocate(cItems, hint);
#else /* ? STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT */
        STLSOFT_SUPPRESS_UNUSED(hint);

        return get_allocator().allocate(cItems);
#endif /* STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT */
    }

    pointer allocate_(size_type cItems)
    {
#ifdef STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT
        return get_allocator().allocate(cItems, NULL);
#else /* ? STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT */
        return get_allocator().allocate(cItems);
#endif /* STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT */
    }

    void deallocate_(pointer p, size_type cItems)
    {
        STLSOFT_ASSERT(NULL != p);

#ifdef STLSOFT_LF_ALLOCATOR_DEALLOCATE_HAS_COUNT
        get_allocator().deallocate(p, cItems);
#else /* ? STLSOFT_LF_ALLOCATOR_DEALLOCATE_HAS_COUNT */
        STLSOFT_SUPPRESS_UNUSED(cItems);

        get_allocator().deallocate(p);
#endif /* STLSOFT_LF_ALLOCATOR_DEALLOCATE_HAS_COUNT */
    }

    pointer reallocate_(pointer p, size_type cItems, size_type cNewItems)
    {
        pointer new_p   =   allocate_(cNewItems, p);

        // This test is needed, since some allocators may not throw
        // bad_alloc
        if(NULL != new_p)
        {
            block_copy(new_p, p, cItems);

            deallocate_(p, cItems);
        }

        return new_p;
    }
protected:
    static void block_copy(pointer dest, const_pointer src, size_type cItems)
    {
        pod_copy_n(dest, src, cItems);
    }
    static void block_set(pointer dest, size_type cItems, const_reference value)
    {
        pod_fill_n(dest, cItems, value);
    }
/// @}

/// \name Construction
/// @{
public:
    /// \brief Constructs an auto_buffer with the given number of elements
    ///
    /// Constructs an auto_buffer with the given number of elements. If the
    /// allocation fails by throwing an exception, that exception is passed
    /// through to the caller. If allocation fails by returning a null
    /// pointer the auto_buffer instance is correctly constructed, and the
    /// \link #size size() \endlink method returns 0.
    ///
    /// \see \link #size size() \endlink
    /// \param cItems The number of items in the constructed instance
    ss_explicit_k auto_buffer(size_type cItems)
        : m_buffer((space < cItems) ? allocate_(cItems) : const_cast<pointer>(&m_internal[0]))
        , m_cItems((NULL != m_buffer) ? cItems : 0)
        , m_bExternal(space < cItems)
    {
        // Can't create one with an empty buffer. Though such is not legal
        // it is supported by some compilers, so we must ensure it cannot be
        // so
        STLSOFT_STATIC_ASSERT(0 != space);

        // These assertions ensure that the member ordering is not
        // changed, invalidating the initialisation logic of m_buffer and
        // m_cItems. The runtime assert is included for those compilers that
        // do not implement compile-time asserts.
#ifdef STLSOFT_CF_USE_RAW_OFFSETOF_IN_STATIC_ASSERT
        STLSOFT_STATIC_ASSERT(STLSOFT_RAW_OFFSETOF(class_type, m_buffer) < STLSOFT_RAW_OFFSETOF(class_type, m_cItems));
#endif /* STLSOFT_CF_USE_RAW_OFFSETOF_IN_STATIC_ASSERT */
        STLSOFT_MESSAGE_ASSERT("m_buffer must be before m_cItems in the auto_buffer definition", stlsoft_reinterpret_cast(ss_byte_t*, &m_buffer) < stlsoft_reinterpret_cast(ss_byte_t*, &m_cItems));

#ifndef _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
        // Use the must_be_pod constraint to ensure that
        // no type is managed in auto_buffer which would result in
        // dangerous mismanagement of the lifetime of its instances.
        //
        // Preprocessor specification of _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
        // prevents this, but the natural rules of the language will
        // still prevent non POD types being placed in m_internal[].
        stlsoft_constraint_must_be_pod(value_type);
#endif /* _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD */

        STLSOFT_ASSERT(is_valid());
    }
    /// \brief Releases the allocated element array
    ///
    /// Releases any allocated memory. If the internal memory buffer was
    /// used, then nothing is done, otherwise the allocated memory is
    /// returned to the allocator.
#if defined(STLSOFT_CF_EXCEPTION_SIGNATURE_SUPPORT)
    ~auto_buffer()
#else /* ? STLSOFT_CF_EXCEPTION_SIGNATURE_SUPPORT */
    ~auto_buffer() stlsoft_throw_0()
#endif /* STLSOFT_CF_EXCEPTION_SIGNATURE_SUPPORT */
    {
        STLSOFT_ASSERT(is_valid());

        if(is_in_external_array_())
        {
            STLSOFT_ASSERT(NULL != m_buffer);
            STLSOFT_ASSERT(m_bExternal);
            STLSOFT_ASSERT(&m_internal[0] != m_buffer);

            deallocate_(m_buffer, m_cItems);
        }
    }
/// @}

/// \name Operations
/// @{
private:
    // Policy functions
    ss_bool_t   is_in_external_array_() const
    {
#if defined(STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK)
        // Old implementation always uses internal array if size() <= internal_size()
        STLSOFT_ASSERT((space < m_cItems) == (m_buffer != &m_internal[0]));

        return space < m_cItems;
#else /* ? STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK */
        // Old implementation always uses internal array if size() <= internal_size()
//        STLSOFT_ASSERT((m_buffer != &m_internal[0]) || !(space < m_cItems));
        STLSOFT_ASSERT((m_buffer != &m_internal[0]) == m_bExternal);
        STLSOFT_ASSERT(m_bExternal || !(space < m_cItems));

//        return m_buffer != &m_internal[0];
        return m_bExternal;
#endif /* STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK */
    }

public:
    /// \brief Expands or contracts the number of items in the buffer
    ///
    /// \param cItems The number of items to change in the buffer. If 0, the
    ///   external array (if allocated) will be deallocated.
    /// \return Returns \c true if successful. Function failure occurs when
    ///   sufficient storage for the requested items cannot be allocated. In
    ///   that case, std::bad_alloc will be throw for allocators that
    ///   support it, otherwise the function will return \c false. In either
    ///   case, the original storage and contents of the buffer will remain
    ///   unchanged.
    ///
    /// \note When reducing the number of elements, the implementation
    ///   favours speed above memory consumption. If the new item size is
    ///   still larger than the internal storage size (\c internal_size())
    ///   then the heap allocated block will not be changed (i.e. it will
    ///   not be exchanged for a smaller block).
    ///
    /// \note As from STLSoft version 1.9, the external array is not
    ///   discarded in favour of the internal array when
    ///   <code>0 < cItems < internal_size()</code>.
    ///   Only <code>resize(0)</code> will deallocate the external array.
    ss_bool_t resize(size_type cItems)
    {
        STLSOFT_ASSERT(is_valid());

        // There are four changes possible:
        //
        // 1. Expansion within the internal buffer
        // 2. Contraction within the internal buffer
        // 3. Expansion from the internal buffer to an allocated buffer
        // 4. Contraction from an allocated buffer to the internal buffer
        //  4.a Where n is 0, or when STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK is defined
        //  4.b Where 0 < n <= internal_size() - this is new behaviour - we do not go to the internal array
        // 5. Expansion from the allocated buffer to another allocated buffer
        // 6. Contraction from the allocated buffer to another allocated buffer

        if(m_cItems < cItems)
        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -