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 + -
显示快捷键?