📄 carray_adaptors.hpp
字号:
}
catch(...)
{
if(size() != oldSize)
{
MFCSTL_ASSERT(size() == oldSize + 1);
get_CArray().RemoveAt(static_cast<int>(index), 1);
}
throw;
}
return begin() + index;
}
/// \brief Inserts a number of copies of the given value 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 n The number of values to insert
/// \param value The value to be inserted
///
/// \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
void insert(iterator pos, size_type n, value_type const &value)
{
// Precondition checks
MFCSTL_ASSERT(pos == end() || (pos >= begin() && pos < end()));
difference_type index = pos - begin();
if(empty())
{
MFCSTL_ASSERT(0 == index);
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
///
/// The adaptor, being a facade, is
///
/// It is used as follows:
///
/// \htmlonly
/// <pre>
/// 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -