おそらく車輪の再発明ですが、場合によっては非常に便利です。
// substring_container_adapter.h
//
// substring_container_adapter is useful for treating a single master string as a collection of substrings
// for the purpose of enumerating over those substrings (read-only)
//
// NOTES:
// (1) sequential forward access is reasonably efficient, but random access is definitely not very efficient. (bidirectional could be implemented)
// (2) the strings must be valid for the lifetime of the adapter and any enumerators you obtain from the adapter
// (3) uses a greedy algorithm - so whole sequences of delimiters are considered one separator, rather than multiple separators
namespace details
{
template <typename charT>
class substring_container_adapter
{
public:
struct iterator : public std::iterator<std::forward_iterator_tag, const charT *>
{
// iterator constructor
iterator(const charT * pszPosition, const charT * pszDelimeters)
: m_pszPosition(pszPosition)
, m_pszDelimeters(pszDelimeters)
, m_pszEnd(FindOneOfOrNil(pszPosition, pszDelimeters))
{ }
// supported relational operators
bool operator == (const iterator & rhs) const { return m_pszPosition == rhs.m_pszPosition; }
bool operator != (const iterator & rhs) const { return m_pszPosition != rhs.m_pszPosition; }
bool operator < (const iterator & rhs) const { return m_pszPosition < rhs.m_pszPosition; }
// increment to next substring
iterator & operator ++ ()
{
const charT * pszNext = SkipDelimeters(m_pszEnd, m_pszDelimeters);
if (pszNext)
{
m_pszPosition = pszNext;
m_pszEnd = FindOneOfOrNil(m_pszPosition, m_pszDelimeters);
}
else
{
m_pszPosition += GetLength(m_pszPosition);
}
return *this;
}
// postfix increment
const iterator operator ++ (int)
{
// note: the const return type flags misuse patterns (see More Effective C++, Item 6)
iterator old(*this);
++(*this);
return old;
}
// dereference == CString
CString operator * () const { return CString(m_pszPosition, static_cast<int>(m_pszEnd - m_pszPosition)); }
// iterators on our characters
const charT * begin() const { return m_pszPosition; }
const charT * end() const { return m_pszEnd; }
private:
const charT * m_pszPosition;
const charT * m_pszDelimeters;
const charT * m_pszEnd;
};
typedef iterator const_iterator;
public:
substring_container_adapter(const charT * pszString, const charT * pszDelimeters)
: m_pszString(pszString)
, m_pszDelimiters(pszDelimeters)
, m_end(pszString + GetLength(pszString), m_pszDelimiters)
{ }
// iterators
iterator begin() const { return iterator(m_pszString, m_pszDelimiters); };
iterator end() const { return m_end; };
private:
const charT * m_pszString; // zero-terminated character array
const charT * m_pszDelimiters; // delimiters
const iterator m_end; // end delimiter
};
}
typedef details::substring_container_adapter<TCHAR> substring_container_adapter;