mapiter.h
来自「Data Replication Prototype Using ADO」· C头文件 代码 · 共 856 行 · 第 1/3 页
H
856 行
/*///////////////////////////////////////////////////////////////////////////////
// Filename: mapIter.h
// Contains the following externally visible objects:
// mfciter::[map type]::iterator
// mfciter::[map type]::const_iterator
// forward iterators that move through a sequence
// returned by the accessor freestanding functions mfciter::begin() and mfciter::end()
// Notes:
// This header file inserts mutable and const iterators on MFC map containers into
// the mfciter namespace, as well as accessor functions begin() and end(). As this is a complex
// template implementation in this header file, please do not read through the template
// classes definition/implementation to try to understand the class interface.
// The iterators created iterate over MFC maps and fully support the stdc++lib requirements
// of forward iterators, which therefore allows them to be used with any stdc++lib
// algorithm (found in header <algorithm>) that works upon forward iterators.
//
// To access the iterators at the beginning and the ending of a MFC map sequence, call
// the freestanding functions mfciter::begin() and mfciter::end() (see note on a CTypedPtrMap caveat),
// passing the MFC map. The iterator returned will either be a mfciter::base_map::iterator or
// mfciter::base_map::const_iterator depending upon the cv qualification of the MFC map.
// mfciter::iterator allows modification of the VALUE field of the map entry, while
// mfciter::const_iterator does not.
//
// [NOTE: Microsoft Visual C++ 6.0 generates an internal compiler error if the iterator
// accessor freestanding functions use the overloaded template function mfciter::begin() and
// mfciter::end() on CTypedPtrMap. Until Microsoft fixes this error, the accessor functions
// for CTypedPtrMap have to be prefixed with a unique string. Once the error is fixed,
// hopefully all CTypedPtrMap accessor functions can be named mfciter::begin() and
// mfciter::end(). See the table below to identify the appropriate name for the freestanding
// accessor function.]
//
// The real type of the iterator returned depends upon the MFC map that is passed
// into the mfciter::begin() or mfciter::end() function. Use the following table
// to determine the correct map type. Note that most of the types require template
// parameters to be filled in that describe the KEY and VALUE fields of the MFC map.
//
// iterator/const_iterator MFC map
// mfciter::cmap<KEY,VALUE>::iterator/const_iterator CMap<KEY,ARG_KEY,VALUE,ARG_VALUE> template
// mfciter::tppmap<KEY,VALUE>::iterator/const_iterator CTypedPtrMap<CMapPtrToPtr, KEY, VALUE> template
// accessed by functions mfciter::tpp_begin() and mfciter::tpp_end()
// mfciter::tpwmap<KEY,VALUE>::iterator/const_iterator CTypedPtrMap<CMapPtrToWord, KEY, VALUE> template
// accessed by functions mfciter::tpw_begin() and mfciter::tpw_end()
// mfciter::tsomap<KEY,VALUE>::iterator/const_iterator CTypedPtrMap<CMapStringToOb, KEY, VALUE> template
// accessed by functions mfciter::tso_begin() and mfciter::tso_end()
// mfciter::tspmap<KEY,VALUE>::iterator/const_iterator CTypedPtrMap<CMapStringToPtr, KEY, VALUE> template
// accessed by functions mfciter::tsp_begin() and mfciter::tsp_end()
// mfciter::twomap<KEY,VALUE>::iterator/const_iterator CTypedPtrMap<CMapWordToOb, KEY, VALUE> template
// accessed by functions mfciter::two_begin() and mfciter::two_end()
// mfciter::twpmap<KEY,VALUE>::iterator/const_iterator CTypedPtrMap<CMapWordToPtr, KEY, VALUE> template
// accesesd by functions mfciter::twp_begin() and mfciter::twp_end()
// mfciter::ppmap::iterator/const_iterator CMapPtrToPtr
// mfciter::pwmap::iterator/const_iterator CMapPtrToWord
// mfciter::somap::iterator/const_iterator CMapStringToOb
// mfciter::spmap::iterator/const_iterator CMapStringToPtr
// mfciter::ssmap::iterator/const_iterator CMapStringToString
// mfciter::womap::iterator/const_iterator CMapWordToOb
// mfciter::wpmap::iterator/const_iterator CMapWordToPtr
//
// The syntax for iterating through an MFC map is very similar to the syntax for
// iterating through a stdc++lib map:
// ex)
// std::map<int,CFoo> myStdCppLibMap;
// for (std::map<int,CFoo>::iterator ii=myStdCppLibMap.begin(); ii!=myStdCppLibMap.end(); ++ii)
// ;
// CMap<int,int,CFoo*,CFoo*> myMfcMap;
// for (mfciter::cmap<int,CFoo*>::iterator jj=mfciter::begin(myMfcMap); jj!=mfciter::end(myMfcMap); ++jj)
// ;
///////////////////////////////////////////////////////////////////////////////*/
/* Aliaksei 08/21/01
Taken from the CUJ article
September 1999
Volume 17 Number 9
STL-Style Iterators for MFC
Kevin Kostrzewa
http://www.cuj.com
*/
#ifndef _INC_MFCITER_MAPITER_H_
#define _INC_MFCITER_MAPITER_H_
#include <iterator>
#pragma warning(disable:4097)
// namespace which holds iterators on mfc collections
namespace mfciter
{
////////////////////////////////////////////////////////////////////////////////
// base_map definition/implementation
// non-instantiatable template struct that holds the member types iterator
// and const_iterator. all template structs derived from this struct specialize
// at least the MAP template parameter. This struct should not be used on the
// left hand side of the scope resolution operator when giving the type of an iterator.
// Rather, a struct derived from this struct should be used.
template<class KEY, class VALUE, class MAP>
struct base_map
{
// forward declarations
class _iterator;
class _const_iterator;
typedef MAP collection_tp;
////////////////////////////////////////////////////////////////////////////////
// _modifiable_value implementation
// Proxy class that allows the return of operator*()/operator->() from _iterator
// to have the VALUE field (but not the KEY field) modifiable. The version that does
// work (the MAP/KEY constructor) is only creatable by friend _iterator. The default
// version is creatable by all clients, so _iterator can have a pair<KEY,_mutate_value_tp>
// (template pair<> is the constructor).
class _modifiable_value
{
public:
// CREATORS
_modifiable_value() :
m_col(NULL)
{}
private:
_modifiable_value(collection_tp &col, const KEY &ky) : // only version of this object that does actual work.
m_col(&col),
m_key(ky)
{}
public:
// MODIFIERS
// proxy function of this class to allow modification of VALUE to flow to the contained MFC map
_modifiable_value &operator=(const VALUE &val)
{
m_col->SetAt(m_key, val);
return *this;
}
// ACCESSORS
// These functions make this class acts like a VALUE instance.
operator const VALUE &() const
{
return (*m_col)[m_key];
}
const VALUE *operator&() const
{
return &(*m_col)[m_key];
}
private:
// DATA
collection_tp *m_col; // referred to map (or NULL)
KEY m_key; // key whose value we might change
// Our dear friends
friend class _iterator; // to allow _iterator to call the private constructor
};
// typedefs/consts for use inside this struct
typedef std::pair<KEY, VALUE> value_tp;
typedef const std::pair<KEY, VALUE> const_value_tp;
// Aliaksei typedef-ing changed to inheritance
// typedef std::pair<const KEY, _modifiable_value> mutable_value_tp;
class mutable_value_tp : public std::pair<const KEY, _modifiable_value>
{
public:
mutable_value_tp() {}
mutable_value_tp(const KEY& key, const _modifiable_value& value)
: std::pair<const KEY, _modifiable_value>(key, value) {}
};
typedef POSITION index_tp;
enum { end_of_sequence=NULL }; // can't use "static const" because vc6 doesn't support that yet.
// The main typedefs for use outside this struct
typedef _iterator iterator;
typedef _const_iterator const_iterator;
////////////////////////////////////////////////////////////////////////////////
// base_map<KEY,VALUE,MAP>::_const_iterator definition/implementation
// stdc++lib forward iterator on a MFC map. Does not allow modification of the
// members that it iterates. The member m_refRet allows operator*() and operator->()
// to return a reference to the KEY,VALUE pair. m_pos == NULL means that
// we are at the end of the iteration sequence.
class _const_iterator : public std::iterator<std::forward_iterator_tag, value_tp>
{
public:
// CREATORS
_const_iterator() :
m_col(NULL),
m_pos(reinterpret_cast<index_tp>(end_of_sequence))
{}
explicit _const_iterator(const collection_tp &col) :
m_col(const_cast<collection_tp *>(&col)), // const_cast only to allow derived _iterator to mutate the map
m_pos((col.GetCount()>0) ? col.GetStartPosition() : reinterpret_cast<index_tp>(end_of_sequence))
{}
_const_iterator(const _const_iterator &other) : // copy all except for m_refRet, as that is not necessary
m_col(other.m_col),
m_pos(other.m_pos)
{}
public:
// MODIFIERS
_const_iterator &operator=(const _const_iterator &other)
{
// copy all members except for m_refRet, as that is not necessary
m_col = other.m_col;
m_pos = other.m_pos;
return *this;
}
_const_iterator &operator++()
{
// ASSERT:cannot advance through a sequence unless we have a valid
// container and are not already pointing to the end of that sequence.
ASSERT(reinterpret_cast<index_tp>(end_of_sequence) != m_pos);
ASSERT(AfxIsValidAddress(m_col, sizeof(*m_col), FALSE));
// Create temporary KEY/VALUE pair on the stack because advancement
// through an MFC map requires access to the current KEY/VALUE pair
KEY k;
VALUE v;
m_col->GetNextAssoc(m_pos, k, v);
return *this;
}
const _const_iterator operator++(int)
{
const _const_iterator ret(*this);
operator++();
return ret;
}
public:
// ACCESSORS
const_value_tp &operator*() const
{
// ASSERT:cannot access a value referred to by an iterator unless
// we have a valid container and are not already pointing to the end
// of that sequence.
ASSERT(reinterpret_cast<index_tp>(end_of_sequence) != m_pos);
ASSERT(AfxIsValidAddress(m_col, sizeof(*m_col), FALSE));
// Create a temporary index_tp on the stack because access of an
// element of an MFC map requires advancement through the map.
index_tp posIgnored(m_pos);
m_col->GetNextAssoc(posIgnored, m_refRet.first, m_refRet.second);
// m_refRet allows us to return by-reference, rather than returning by-value
return m_refRet;
}
const_value_tp *operator->() const
{
return &operator*();
}
//template <typename T> bool operator == (const T &other) const
bool operator == (const _const_iterator &other) const
{
return
(reinterpret_cast<base_map<KEY,VALUE,MAP>::index_tp>(base_map<KEY,VALUE,MAP>::end_of_sequence)==m_pos &&
reinterpret_cast<base_map<KEY,VALUE,MAP>::index_tp>(base_map<KEY,VALUE,MAP>::end_of_sequence)==other.m_pos) ||
(m_col==other.m_col && m_pos==other.m_pos);
}
//template <typename T> bool operator != (const T &other)
bool operator != (const _const_iterator &other) const
{
return !(*this == other);
}
protected:
// DATA
// All data is protected so derived _iterator can use it.
collection_tp *m_col; // map that we refer to, or NULL for empty iterator
index_tp m_pos; // position in our map, or end_of_sequence
mutable value_tp m_refRet; // for functions that return iterated value by reference.
// mutable to allow changing in operator* and operator-> const functions
// Our dear friends
//friend bool operator==(const _const_iterator &i1, const _const_iterator &i2);
//template<class KEY, class VALUE, class MAP>
// friend bool operator==(const base_map<KEY,VALUE,MAP>::_const_iterator &i1, const base_map<KEY,VALUE,MAP>::_const_iterator &i2);
};
////////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?