📄 collection_sequence.hpp
字号:
typedef ss_typename_type_k enumerator_sequence_type::reference reference;
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
typedef ss_typename_type_k enumerator_sequence_type::reference_type reference_type; // For backwards compatiblity
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
/// \brief The mutating (non-const) pointer type
typedef ss_typename_type_k enumerator_sequence_type::pointer pointer;
/// \brief The non-mutating (const) pointer type
typedef ss_typename_type_k enumerator_sequence_type::const_pointer const_pointer;
/// \brief The mutating (non-const) iterator type
typedef ss_typename_type_k enumerator_sequence_type::iterator iterator;
/// \brief The non-mutating (const) iterator type
typedef ss_typename_type_k enumerator_sequence_type::const_iterator const_iterator;
/// \brief Cloning policy type
typedef ss_typename_type_k enumerator_sequence_type::cloning_policy_type cloning_policy_type;
/// \brief Iterator tag type
typedef ss_typename_type_k enumerator_sequence_type::iterator_tag_type iterator_tag_type;
/// \brief Retrieval quanta
enum { retrievalQuanta = enumerator_sequence_type::retrievalQuanta };
/// \brief The policy for acquiring the enumerator from the collection
typedef EAP enumerator_acquisition_policy_type;
/// \brief Type of the current parameterisation
typedef collection_sequence<CI, EI, V, VP, R, CP, Q, EAP> class_type;
/// \brief The size type
typedef ss_typename_type_k enumerator_sequence_type::size_type size_type;
/// \brief The difference type
typedef ss_typename_type_k enumerator_sequence_type::difference_type difference_type;
/// @}
public:
/// \brief Conversion constructor
///
/// \param i The enumeration interface pointer to adapt
/// \param bAddRef Causes a reference to be added if \c true, otherwise the sequence is deemed to <i>sink</i>, or consume, the interface pointer
/// \param quanta The actual quanta required for this instance. Must be <= Q
///
/// \note This does not throw an exception, so it is safe to be used to "eat" the
/// reference. The only possible exception to this is if COMSTL_ASSERT(), which is
/// used to validate that the given quanta size is within the limit specified in
/// the specialisation, has been redefined to throw an exception. But since
/// precondition violations are no more recoverable than any others (see the article
/// "The Nuclear Reactor and the Deep Space Probe"), this does not represent
/// a concerning contradiction to the no-throw status of the constructor.
collection_sequence(collection_interface_type *i, cs_bool_t bAddRef, size_type quanta = 0)
: m_i(i)
, m_quanta(validate_quanta_(quanta))
{
COMSTL_ASSERT(NULL != i);
COMSTL_MESSAGE_ASSERT("Cannot set a quantum that exceeds the value specified in the template specialisation", quanta <= retrievalQuanta); // Could have named these things better!
if(bAddRef)
{
m_i->AddRef();
}
COMSTL_ASSERT(is_valid());
}
/// \brief Releases the adapted interface pointer
~collection_sequence() stlsoft_throw_0()
{
COMSTL_ASSERT(is_valid());
m_i->Release();
}
/// \name Iteration
/// @{
public:
/// \brief Begins the iteration
///
/// \return An iterator representing the start of the sequence
iterator begin() const
{
COMSTL_ASSERT(is_valid());
LPUNKNOWN punkEnum;
HRESULT hr = enumerator_acquisition_policy_type::acquire(m_i, &punkEnum);
if(SUCCEEDED(hr))
{
enumerator_interface_type *ei;
hr = punkEnum->QueryInterface(IID_traits<enumerator_interface_type>::iid(), reinterpret_cast<void**>(&ei));
punkEnum->Release();
if(SUCCEEDED(hr))
{
COMSTL_ASSERT(is_valid());
return enumerator_sequence_type(ei, false, m_quanta).begin();
}
else
{
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
COMSTL_ASSERT(is_valid());
STLSOFT_THROW_X(com_exception("the enumerator does not provide the requested interface", hr));
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
}
}
else
{
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
COMSTL_ASSERT(is_valid());
STLSOFT_THROW_X(com_exception("enumerator could not be elicited from the collection", hr));
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
}
COMSTL_ASSERT(is_valid());
return iterator();
}
/// \brief Ends the iteration
///
/// \return An iterator representing the end of the sequence
iterator end() const
{
COMSTL_ASSERT(is_valid());
return iterator();
}
/// @}
/// \name Capacity
/// @{
public:
/** \brief Returns the number of items in the collection
*
\code
IGUIDCollection *penGUIDs = . . .; // Create an instance from wherever
collection_sequence_t guids(penGUIDs, false); // Eat the reference
size_t numItems = guids.size(); // Evaluate the number of elements in the collection
\endcode
*
*
* \note This method will not compile for collection interfaces
* that do not contain the get_Count method
*/
size_type size() const
{
COMSTL_ASSERT(is_valid());
ULONG count;
HRESULT hr = m_i->get_Count(&count);
COMSTL_ASSERT(is_valid());
return SUCCEEDED(hr) ? count : 0;
}
/// @}
/// \name Invariant
/// @{
private:
cs_bool_t is_valid() const
{
if(NULL == m_i)
{
return false;
}
return true;
}
/// @}
// Implementation
private:
static size_type validate_quanta_(size_type quanta)
{
COMSTL_MESSAGE_ASSERT("Cannot set a quantum that exceeds the value specified in the template specialisation", quanta <= retrievalQuanta); // Could have named these things better!
if( 0 == quanta ||
quanta > retrievalQuanta)
{
quanta = retrievalQuanta;
}
return quanta;
}
// Members
private:
collection_interface_type *m_i;
size_type const m_quanta;
// Not to be implemented
private:
collection_sequence(class_type const&);
class_type const& operator =(class_type const&);
};
////////////////////////////////////////////////////////////////////////////
// Unit-testing
#ifdef STLSOFT_UNITTEST
# include "./unittest/collection_sequence_unittest_.h"
#endif /* STLSOFT_UNITTEST */
/* ////////////////////////////////////////////////////////////////////// */
#ifndef _COMSTL_NO_NAMESPACE
# if defined(_STLSOFT_NO_NAMESPACE) || \
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace comstl
# else
} // namespace stlsoft::comstl_project
} // namespace stlsoft
# endif /* _STLSOFT_NO_NAMESPACE */
#endif /* !_COMSTL_NO_NAMESPACE */
/* ////////////////////////////////////////////////////////////////////// */
#endif /* !COMSTL_INCL_COMSTL_COLLECTIONS_HPP_COLLECTION_SEQUENCE */
/* ////////////////////////////////////////////////////////////////////// */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -