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

📄 carray_adaptors.hpp

📁 新版本TR1的stl
💻 HPP
📖 第 1 页 / 共 4 页
字号:
            assign(n, value);
        }
        else
        {
            const size_type oldSize =   size();

            resize(size());

            try
            {
                try
                {
                    if(n > 0) // Can't pass 0 to InsertAt()
                    {
                        get_CArray().InsertAt(static_cast<int>(index), value, n);
                    }
                }
                catch(CMemoryException *px)
                {
                    exception_translation_policy_type::handle(px);
                }
                catch(mfcstl_ns_qual_std(bad_alloc) &x)
                {
                    exception_translation_policy_type::handle(x);
                }
            }
            catch(...)
            {
                if(size() != oldSize)
                {
                    MFCSTL_ASSERT(size() == oldSize + n);

                    get_CArray().RemoveAt(static_cast<int>(index), size() - oldSize);
                }

                throw;
            }
        }
    }
    /// \brief Inserts the elements in the range [first, last) at the given position
    ///
    /// \param pos The position at which to insert. The value(s) will be inserted
    ///   before the element referred to by pos, or at the end if pos == end()
    /// \param first The start of the range of values to insert
    /// \param last The (one past the) end of the range of values to insert
    ///
    /// \note All iterators, pointers and references are invalidated
    ///
    /// \note Any elements after the insertion position are moved using memmove,
    ///   rather than by copy construction. If the element type maintains
    ///   pointers to its internal members, or to its peer elements, then these
    ///   relationships will be broked, and the subsequent behaviour of the
    ///   program will be undefined
    template <ss_typename_param_k I2>
    void insert(iterator pos, I2 first, I2 last)
    {
        // Precondition checks
        MFCSTL_ASSERT(is_valid_source_range_(first, last));
        MFCSTL_ASSERT(pos == end() || (pos >= begin() && pos < end()));

        array_type                  ar;
        CArray_iadaptor<array_type
                    ,   array_traits_type
                    >               arp(ar);
        arp.assign(first, last);
        difference_type             index   =   pos - begin();
        const size_type             oldSize =   size();
        const size_type             n       =   arp.size();

        resize(size());

        try
        {
            try
            {
                get_CArray().InsertAt(static_cast<int>(index), &ar);
            }
            catch(CMemoryException *px)
            {
                exception_translation_policy_type::handle(px);
            }
            catch(mfcstl_ns_qual_std(bad_alloc) &x)
            {
                exception_translation_policy_type::handle(x);
            }
        }
        catch(...)
        {
            if(size() != oldSize)
            {
                MFCSTL_ASSERT(size() == oldSize + n);

                get_CArray().RemoveAt(static_cast<int>(index), size() - oldSize);
            }

            throw;
        }
    }
    /// \brief Erases the element at the given position
    ///
    /// \param pos The position of the element to be removed
    ///
    /// \retval The position of the value immediately following the element erased
    ///
    /// \note Any iterators, pointers or references to elements at or after \c
    ///   pos will be invalidated. Those before \c pos remain valid
    ///
    /// \note Any elements after the erasure position are moved using memmove,
    ///   rather than by copy construction. If the element type maintains
    ///   pointers to its internal members, or to its peer elements, then these
    ///   relationships will be broked, and the subsequent behaviour of the
    ///   program will be undefined
    iterator erase(iterator pos) stlsoft_throw_0()
    {
        // Precondition checks
        MFCSTL_ASSERT(pos == end() || (pos >= begin() && pos < end()));

        difference_type index = pos - begin();
        get_CArray().RemoveAt(static_cast<int>(index), 1);

        // Postcondition checks
        MFCSTL_ASSERT(pos == begin() + index);

        resize(size());

        return pos;
    }
    /// \brief Erases a range of elements from the array
    ///
    /// \param first The first element in the range to be removed
    /// \param last The (one past the) end element in the range to be removed
    ///
    /// \retval The position of the value immediately following the elements erased
    ///
    /// \note Any iterators, pointers or references to elements at or after \c
    ///   first will be invalidated. Those before \c first remain valid
    ///
    /// \note Any elements after the erasure position are moved using memmove,
    ///   rather than by copy construction. If the element type maintains
    ///   pointers to its internal members, or to its peer elements, then these
    ///   relationships will be broked, and the subsequent behaviour of the
    ///   program will be undefined
    iterator erase(iterator first, iterator last) stlsoft_throw_0()
    {
        // Precondition checks
        MFCSTL_ASSERT(first <= last);
        MFCSTL_ASSERT(first == end() || (first >= begin() && first < end()));
        MFCSTL_ASSERT(last == end() || (last >= begin() && last < end()));

        difference_type index = first - begin();
        get_CArray().RemoveAt(static_cast<int>(index), mfcstl_ns_qual_std(distance)(first, last));

        // Postcondition checks
        MFCSTL_ASSERT(first == begin() + index);

        resize(size());

        return first;
    }
    /// \brief Removes all the elements from the array
    void clear() stlsoft_throw_0()
    {
        get_CArray().RemoveAll();

        resize(size());
    }

#ifdef MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT
    /// \brief Efficiently exchanges the contents with those of another array
    ///   by swapping the internal structures
    ///
    /// \param rhs The instance whose contents will be exchanged with the callee
    ///
    /// \note This method is only defined if the preprocessor symbol
    ///   MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT is defined
    void swap(class_type& rhs) stlsoft_throw_0()
    {
        mfcstl::CArray_swap(this->get_CArray(), rhs.get_CArray());
    }
#endif /* MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT */

    /// \brief Exchanges the contents with those of another array by copying
    ///   each of the constituents, using a temporary array instance.
    ///
    /// \param rhs The instance whose contents will be exchanged with the callee
    void         swap_by_copy(class_type& rhs)
    {
        class_type  t       =   rhs;
                    rhs     =   *this;
                    *this   =   t;
    }
/// @}

/// \name Implementation
/// @{
private:
    template <ss_typename_param_k I2>
# if defined(STLSOFT_COMPILER_IS_MWERKS)
    // There seems to be a bug in CodeWarrior that makes it have a cow with iterator tags by value, so we just use a ptr
    void clear_and_assign_(I2 first, I2 last, stlsoft_ns_qual_std(input_iterator_tag) const*)
# else /* ? compiler */
    void clear_and_assign_(I2 first, I2 last, stlsoft_ns_qual_std(input_iterator_tag))
# endif /* compiler */
    {
        clear();

        mfcstl_ns_qual_std(copy)(first, last, mfcstl_ns_qual_std(back_inserter)<class_type>(*this));
    }
    template <ss_typename_param_k I2>
# if defined(STLSOFT_COMPILER_IS_MWERKS)
    // There seems to be a bug in CodeWarrior that makes it have a cow with iterator tags by value, so we just use a ptr
    void clear_and_assign_(I2 first, I2 last, stlsoft_ns_qual_std(forward_iterator_tag) const*)
# else /* ? compiler */
    void clear_and_assign_(I2 first, I2 last, stlsoft_ns_qual_std(forward_iterator_tag))
# endif /* compiler */
    {
        resize(mfcstl_ns_qual_std(distance)(first, last));

        mfcstl_ns_qual_std(copy)(first, last, begin());
    }

    template <ss_typename_param_k I2>
    void clear_and_assign_(I2 first, I2 last)
    {
# if defined(STLSOFT_COMPILER_IS_GCC) && \
     __GNUC__ < 3
        typedef ss_typename_type_k mfcstl_ns_qual_std(iterator_traits)<I2> traits_t;

        clear_and_assign_(first, last, traits_t::iterator_category());
# elif defined(STLSOFT_COMPILER_IS_MWERKS)
        clear_and_assign_(first, last, stlsoft_iterator_query_category_ptr(I2, first));
# else /* ? compiler */
        clear_and_assign_(first, last, stlsoft_iterator_query_category(I2, first));
# endif /* compiler */
    }

protected:
#if (   !defined(STLSOFT_COMPILER_IS_MSVC) || \
        _MSC_VER > 1200)
    template <ss_typename_param_k I2>
# if defined(STLSOFT_COMPILER_IS_MWERKS)
    // There seems to be a bug in CodeWarrior that makes it have a cow with iterator tags by value, so we just use a ptr
    static ms_bool_t is_valid_source_range_(I2 first, I2 last, stlsoft_ns_qual_std(input_iterator_tag) const*)
# else /* ? compiler */
    static ms_bool_t is_valid_source_range_(I2 first, I2 last, stlsoft_ns_qual_std(input_iterator_tag))
# endif /* compiler */
    {
        return true;    // Can't test them, as that eats their state, so have to assume yes
    }
#endif /* compiler */

    template<   ss_typename_param_k I2
            ,   ss_typename_param_k T2
            >
    static ms_bool_t is_valid_source_range_(I2 first, I2 last, T2)
    {
        return true;    // FI and BI don't have <=, so cannot test, so have to assume yes
    }

#if (   !defined(STLSOFT_COMPILER_IS_MSVC) || \
        _MSC_VER > 1200)
    template <ss_typename_param_k I2>
# if defined(STLSOFT_COMPILER_IS_MWERKS)
    // There seems to be a bug in CodeWarrior that makes it have a cow with iterator tags by value, so we just use a ptr
    static ms_bool_t is_valid_source_range_(I2 first, I2 last, stlsoft_ns_qual_std(random_access_iterator_tag) const*)
# else /* ? compiler */
    static ms_bool_t is_valid_source_range_(I2 first, I2 last, stlsoft_ns_qual_std(random_access_iterator_tag))
# endif /* compiler */
    {
        return first <= last;
    }
#endif /* compiler */

    template <ss_typename_param_k I2>
    static ms_bool_t is_valid_source_range_(I2 first, I2 last)
    {
# if defined(STLSOFT_COMPILER_IS_GCC) && \
     __GNUC__ < 3
        typedef ss_typename_type_k mfcstl_ns_qual_std(iterator_traits)<I2> traits_t;

        return is_valid_source_range_(first, last, traits_t::iterator_category());
# elif defined(STLSOFT_COMPILER_IS_MWERKS)
        return is_valid_source_range_(first, last, stlsoft_iterator_query_category_ptr(I2, first));
# elif defined(STLSOFT_COMPILER_IS_DMC)
        return true;
# else /* ? compiler */
        return is_valid_source_range_(first, last, stlsoft_iterator_query_category(I2, first));
# endif /* compiler */
    }

#if 0
    template <ss_typename_param_k T2>
    static ms_bool_t is_valid_source_range_(T2* first, T2* last)
    {
        return first <= last;
    }
#endif /* 0 */

#if 0
    template <ss_typename_param_k T2>
    static ms_bool_t is_valid_source_range_(T2 const* first, T2 const* last)
    {
        return first <= last;
    }
#endif /* 0 */
/// @}

/// \name Not to be implemented
/// @{
private:
    CArray_adaptor_base(class_type const& rhs);
    class_type& operator =(class_type const& rhs);
/// @}
};

#ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
/** \brief Adaptor class, representing a Class Adaptor over the CArray family
 *    of MFC containers
 *
 * \ingroup group__library__collections
 *
 * The adaptor, being a facade, is
 *
 * It is used as follows:
 *
\code
  mfcstl::CArray_cadaptor<CStringArray>   ar;

  // As an MFC CStringArray:
  ar.Add("String 1");
  ar.InsertAt(0, "String 0");

  // As an STL container
  ar.push_back("String 2");
  std::list<CString>  l;
  l.push_back("String 3");
  l.push_back("String 4");
  ar.insert(ar.begin() + 2, l.begin(), l.end());
  std::sort(ar.begin(), ar.end());
\endcode
 *
 * \param A The array class, e.g. CObArray, CArray<long>, etc.
 *
 * \note The elements in an adapted array are moved, during insertion / erasure, rather than copied. This
 *   means that if the elements in the container maintain pointers to their elements, or their peers, then
 *   they are not suitable for use.
 */
#endif /* STLSOFT_DOCUMENTATION_SKIP_SECTION */
template<   ss_typename_param_k A
        ,   ss_typename_param_k T = CArray_traits<A>
        >
class CArray_cadaptor
        : public A
        , public CArray_adaptor_base<A, CArray_cadaptor<A, T>, T>
{
/// \name Member Types
/// @{
private:
    typedef CArray_adaptor_base<A, CArray_cadaptor<A, T>, T>        parent_class_type;
public:
    /// The type of the underlying MFC array
    typedef ss_typename_type_k parent_class_type::array_type        array_type;
    /// The value type
    typedef ss_typename_type_k parent_class_type::value_type        value_type;
    /// The allocator type
    typedef ss_typename_type_k parent_class_type::allocator_type    allocator_type;
    /// The mutating (non-const) reference type
    typedef ss_typename_type_k parent_class_type::reference         reference;
    /// The non-mutating (const) reference type
    typedef ss_typename_type_k parent_class_type::const_reference   const_reference;
    /// The mutating (non-const) pointer type
    typedef ss_typename_type_k parent_class_type::pointer           pointer;
    /// The non-mutating (const) pointer type
    typedef ss_typename_type_k parent_class_type::const_pointer     const_pointer;
    /// The mutating (non-const) iterator type
    typedef ss_typename_type_k parent_class_type::iterator          iterator;
    /// The non-mutating (const) iterator type
    typedef ss_typename_type_k parent_class_type::const_iterator    const_iterator;
    /// The size type
    typedef ss_typename_type_k parent_class_type::size_type         size_type;
    /// The difference type
    typedef ss_typename_type_k parent_class_type::difference_type   difference_type;
    /// The instantiation of the current type
    typedef CArray_cadaptor<A, T>                                   class_type;
/// @}

/// \name Identity
/// @{
private:
    friend class CArray_adaptor_base<A, CArray_cadaptor<A, T>, T>;

    array_type          &get_actual_array()
    {
        return *this;
    }
    array_type const    &get_actual_array() const
    {
        return *this;
    }
/// @}

/// \name Construction
/// @{
public:
    /// Default constructs an instance
    ///
    /// \note It takes a parameter of type <code>allocator_type</code>, but
    /// ignores it. This facilitates adaptation by the standard adaptor
    /// <code>std::stack</code>.
    ss_explicit_k CArray_cadaptor(allocator_type const& = allocator_type())
    {
        parent_class_type::resize(0);   // DMC++ needs it to be qualified. Go figure!
    }
    /// Constructs an instance with the given number of elements
    ///
    /// \param n The number of elements
    explicit CArray_cadaptor(size_type n)
    {
        parent_class_type::resize(n);
    }

⌨️ 快捷键说明

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