📄 carray_adaptors.hpp
字号:
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 + -