📄 carray_adaptors.hpp
字号:
, array_traits_type
> arp(ar);
arp.assign(first, last);
CArray_swap(this->get_CArray(), ar);
}
#else /* ? MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT */
clear_and_assign_(first, last);
#endif /* MFCSTL_CARRAY_SWAP_MEMBERS_SUPPORT */
}
/// @}
/// \name Size and Capacity
/// @{
public:
/// \brief The number of items in the array
size_type size() const
{
return static_cast<size_type>(get_CArray().GetSize());
}
/// \brief The maximum number of items that can be stored in the array
size_type max_size() const
{
return get_allocator().max_size();
}
/// \brief Indicates whether the array is empty
ms_bool_t empty() const
{
return 0 == size();
}
/// \brief Adjusts the number of elements in the array
///
/// \param n The number of elements that the array will contain after resizing
///
/// \note Exception-safety is <b>strong</b> if the default constructor of the value type
/// cannot throw exceptions, otherwise it is weak
void resize(size_type n)
{
try
{
get_CArray().SetSize(n, calc_increment_(n));
}
catch(CMemoryException *px)
{
exception_translation_policy_type::handle(px);
}
catch(mfcstl_ns_qual_std(bad_alloc) &x)
{
exception_translation_policy_type::handle(x);
}
// Postcondition
MFCSTL_ASSERT(size() == n);
}
/// \brief Adjusts the number of elements in the array
///
/// \param n The number of elements that the array will contain after resizing
/// \param value The value of any additional elements created during resizing
///
/// \note Due to the limitations of the underlying CArray-family containers, the
/// additional elements are default constructed and then subjected to
/// copy-assignment.
///
/// \note Exception-safety is <b>weak</b>, but the size is maintained in the case
/// where an exception is thrown by the copy assignment of any new elements.
void resize(size_type n, value_type value)
{
const size_type oldSize = size();
resize(n);
if(oldSize < n)
{
try
{
mfcstl_ns_qual_std(fill_n)(begin() + oldSize, n - oldSize, value);
}
catch(...)
{
resize(oldSize);
throw;
}
}
}
/// @}
/// \name Element access
/// @{
public:
/// \brief Returns a mutable (non-const) reference to the element at the given index
///
/// \param n The requested index. Must be less than size()
///
/// \note The implementation will assert in debug mode if the index is out of range
reference operator [](size_type n)
{
MFCSTL_MESSAGE_ASSERT("index out of bounds", n < size());
return get_CArray()[n];
}
/// \brief Returns a non-mutable (const) reference to the element at the given index
///
/// \param n The requested index. Must be less than size()
///
/// \note The implementation will assert in debug mode if the index is out of range
const_reference operator [](size_type n) const
{
MFCSTL_MESSAGE_ASSERT("index out of bounds", n < size());
return get_CArray()[n];
}
/// \brief Returns a mutable (non-const) reference to the element at the given index
///
/// \param n The requested index. If the index is not less than size() an
/// instance of std::out_of_range will be thrown
reference at(size_type n)
{
if(n >= size())
{
STLSOFT_THROW_X(mfcstl_ns_qual_std(out_of_range)("Invalid index specified"));
}
return (*this)[n];
}
/// \brief Returns a non-mutable (const) reference to the element at the given index
///
/// \param n The requested index. If the index is not less than size() an
/// instance of std::out_of_range will be thrown
const_reference at(size_type n) const
{
if(n >= size())
{
STLSOFT_THROW_X(mfcstl_ns_qual_std(out_of_range)("Invalid index specified"));
}
return (*this)[n];
}
/// \brief Returns a mutable (non-const) reference to the first element in the array
reference front()
{
MFCSTL_MESSAGE_ASSERT("front() called on an empty instance", !empty());
return (*this)[0];
}
/// \brief Returns a mutable (non-const) reference to the last element in the array
reference back()
{
MFCSTL_MESSAGE_ASSERT("back() called on an empty instance", !empty());
return (*this)[size() - 1];
}
/// \brief Returns a non-mutable (const) reference to the first element in the array
const_reference front() const
{
MFCSTL_MESSAGE_ASSERT("front() called on an empty instance", !empty());
return (*this)[0];
}
/// \brief Returns a non-mutable (const) reference to the last element in the array
const_reference back() const
{
MFCSTL_MESSAGE_ASSERT("back() called on an empty instance", !empty());
return (*this)[size() - 1];
}
/// @}
/// \name Iteration
/// @{
public:
/// \brief Returns a mutable (non-const) iterator representing the start of the array
iterator begin()
{
return get_CArray().GetData();
}
/// \brief Returns a mutable (non-const) iterator representing the end of the array
iterator end()
{
return begin() + size();
}
/// \brief Returns a non-mutable (const) iterator representing the start of the array
const_iterator begin() const
{
// This is needed because CXxxxArray::GetData() const returns, e.g., const CObject** instead of CObject* const*
value_type const *p1 = get_CArray().GetData();
value_type *const p2 = const_cast<value_type *const>(p1);
return p2;
}
/// \brief Returns a non-mutable (const) iterator representing the end of the array
const_iterator end() const
{
return begin() + size();
}
#ifdef STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT
/// \brief Returns a mutable (non-const) reverse iterator representing the start of the array
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
/// \brief Returns a mutable (non-const) reverse iterator representing the end of the array
reverse_iterator rend()
{
return reverse_iterator(begin());
}
/// \brief Returns a non-mutable (const) reverse iterator representing the start of the array
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
/// \brief Returns a non-mutable (const) reverse iterator representing the end of the array
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
#endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
/// @}
/// \name Comparison
/// @{
public:
template< ss_typename_param_k A2
, ss_typename_param_k I2
, ss_typename_param_k T2
>
ms_bool_t equal(CArray_adaptor_base<A2, I2, T2> const& rhs) const
{
typedef CArray_adaptor_base<A2, I2, T2> rhs_t;
typedef ss_typename_type_k rhs_t::value_type rhs_value_t;
STLSOFT_STATIC_ASSERT(sizeof(value_type) == sizeof(ss_typename_type_k rhs_t::value_type));
#ifdef STLSOFT_META_HAS_IS_SAME_TYPE
STLSOFT_STATIC_ASSERT((stlsoft::is_same_type<value_type, rhs_value_t>::value));
#endif /* STLSOFT_META_HAS_IS_SAME_TYPE */
return size() == rhs.size() && stlsoft_ns_qual_std(equal)(begin(), end(), rhs.begin());
}
ms_bool_t equal(array_type const& rhs) const
{
array_type const &lhs = this->get_CArray();
return lhs.GetSize() == rhs.GetSize() && stlsoft_ns_qual_std(equal)(begin(), end(), rhs.GetData());
}
template< ss_typename_param_k A2
, ss_typename_param_k I2
, ss_typename_param_k T2
>
ms_bool_t less_than(CArray_adaptor_base<A2, I2, T2> const& rhs) const
{
typedef CArray_adaptor_base<A2, I2, T2> rhs_t;
typedef ss_typename_type_k rhs_t::value_type rhs_value_t;
STLSOFT_STATIC_ASSERT(sizeof(value_type) == sizeof(ss_typename_type_k rhs_t::value_type));
#ifdef STLSOFT_META_HAS_IS_SAME_TYPE
STLSOFT_STATIC_ASSERT((stlsoft::is_same_type<value_type, rhs_value_t>::value));
#endif /* STLSOFT_META_HAS_IS_SAME_TYPE */
return stlsoft_ns_qual_std(lexicographical_compare)(begin(), end(), rhs.begin(), rhs.end());
}
ms_bool_t less_than(array_type const& rhs) const
{
return stlsoft_ns_qual_std(lexicographical_compare)(begin(), end(), rhs.GetData(), rhs.GetData() + rhs.GetSize());
}
template< ss_typename_param_k A2
, ss_typename_param_k I2
, ss_typename_param_k T2
>
ms_bool_t greater_than(CArray_adaptor_base<A2, I2, T2> const& rhs) const
{
typedef CArray_adaptor_base<A2, I2, T2> rhs_t;
typedef ss_typename_type_k rhs_t::value_type rhs_value_t;
STLSOFT_STATIC_ASSERT(sizeof(value_type) == sizeof(ss_typename_type_k rhs_t::value_type));
#ifdef STLSOFT_META_HAS_IS_SAME_TYPE
STLSOFT_STATIC_ASSERT((stlsoft::is_same_type<value_type, rhs_value_t>::value));
#endif /* STLSOFT_META_HAS_IS_SAME_TYPE */
return stlsoft_ns_qual_std(lexicographical_compare)(rhs.begin(), rhs.end(), begin(), end());
}
ms_bool_t greater_than(array_type const& rhs) const
{
return stlsoft_ns_qual_std(lexicographical_compare)(rhs.GetData(), rhs.GetData() + rhs.GetSize(), begin(), end());
}
/// @}
/// \name Modifiers
/// @{
public:
/// \brief Adds the given element to the end of the array
///
/// \param value The value to add to the end of the array
///
/// \note All iterators, pointers and references are invalidated
void push_back(value_type const& value)
{
const size_type oldSize = size();
resize(size());
try
{
try
{
get_CArray().Add(value);
}
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 + 1);
resize(oldSize);
}
throw;
}
}
/// \brief Removes the last element from the non-empty array
///
/// \note The behaviour is undefined if the array is empty
void pop_back() stlsoft_throw_0()
{
// Precondition checks
MFCSTL_MESSAGE_ASSERT("pop_back() called on empty container", !empty());
get_CArray().RemoveAt(get_CArray().GetUpperBound());
}
/// \brief Inserts the given value at the given position
///
/// \param pos The position at which to insert. The value will be inserted
/// before the element referred to by pos, or at the end if pos == end()
/// \param value The value to be inserted
///
/// \retval The position of the inserted value
///
/// \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 broken, and the subsequent behaviour of the
/// program will be undefined
iterator insert(iterator pos, value_type const& value)
{
// Precondition checks
MFCSTL_ASSERT(pos == end() || (pos >= begin() && pos < end()));
difference_type index = pos - begin();
const size_type oldSize = size();
resize(size());
try
{
try
{
get_CArray().InsertAt(static_cast<int>(index), value, 1);
}
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 + 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -