用于MFC容器CObList的STL迭代器 [英] STL iterator for MFC container CObList

查看:162
本文介绍了用于MFC容器CObList的STL迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文件夹类,其中包含两个文件夹文件列表。

I have a Folder class which contains two lists of Folders and Files.

    class Folder : public CObject
    {
public:
    typedef std::string StringT;
     ...
    Container filesInFolder;
    Container foldersInFolder;
    StringT folderName;
    ...
    };

class File : public CObject { ... };

列表来自CObList。 类容器:public CObList 。我需要通过名称和 filesInFolder 按名称和扩展名在 foldersInFolder 中执行搜索。 CObList :: Find不允许我使用谓词。我会正常地使用带谓词的std :: find_if:

Lists derive from CObList. Class Container : public CObList. I need to perform search inside foldersInFolder by name and in filesInFolder by name and extension. CObList::Find does not allow me to use predicates. I would normaly use std::find_if with predicate:

struct Comparator
{
    Folder::StringT stringToCompare;
    bool operator() ( const Folder* lhs )
    {
        return lhs->GetFolderName( ) == stringToCompare;
    }
};

所以我需要一个迭代器才能使用这个函数。在[codeguru上,他们定义了一个类BaseMFCIter] [1],它是std :: iterator的子节点:

So i need an iterator to use this function. On [codeguru they define a class BaseMFCIter][1] which is a child of std::iterator:

#include < iterator >

// Define BaseMFCIter as a standard input iterator.
//
// The template arguments are: 
//  Item: the contained element type
//  Cont: the container type
//  Key:  the access key (defaults to POSITION)

template < class Item, class Cont, class Key = POSITION >
class BaseMFCIter : public std::iterator < std::input_iterator_tag, Item >
{
public:
   // Define types for the 2 member functions to be used:
   typedef Key  (Cont::*GetFirstFunctionPtr) ()     const;
   typedef Item (Cont::*GetNextFunctionPtr)  (Key&) const;

   // Default constructor, makes a null iterator, equal to BaseMFCIter::end()
   BaseMFCIter() : m_pCont(0), m_Pos(0), m_GetFirstFunc(0), m_GetNextFunc(0), m_End(true) {}

   // Constructor taking pointer to container and the iteration functions
   BaseMFCIter(Cont* pCont, GetFirstFunctionPtr pFF, GetNextFunctionPtr pNF) 
      : m_pCont(pCont), m_Pos(0), m_GetFirstFunc(pFF), m_GetNextFunc(pNF)
   { init(); }

   // Copy constructor, initialises iterator to first element
   BaseMFCIter(const BaseMFCIter& vi) : m_pCont(vi.m_pCont), m_Pos(0),
    m_GetFirstFunc(vi.m_GetFirstFunc), m_GetNextFunc(vi.m_GetNextFunc)
   { init(); }

   // Assignment operator, initialises iterator to first element
   BaseMFCIter& operator=(const BaseMFCIter& vi)
   {
      m_pCont       = vi.m_pCont; 
      m_GetFirstFunc    = vi.m_GetFirstFunc;
      m_GetNextFunc = vi.m_GetNextFunc;
      init();  
      return *this; 
   }

   bool operator == (const BaseMFCIter& rhs) const
   { return (m_Pos == rhs.m_Pos && m_End == rhs.m_End); }

   bool operator != (const BaseMFCIter& rhs) const 
   { return !operator==(rhs); }

   BaseMFCIter& operator ++ ()    { advance(); return *this; }
   BaseMFCIter& operator ++ (int) { BaseMFCIter ret(*this); advance(); return ret; }
   Item         operator *  ()    { return m_Item; }
   Item         operator -> ()    { return m_Item; }

   static BaseMFCIter end   ()    { return BaseMFCIter(); } // end() returns default null iterator

private:
   Item  m_Item;      // Current item from container
   Cont* m_pCont;     // Pointer to container
   Key   m_Pos;       // Key to item in container
   bool  m_End;       // Flag to indicate end of container reached

   // Pointers to container iteration functions
   GetFirstFunctionPtr m_GetFirstFunc;
   GetNextFunctionPtr  m_GetNextFunc;

   // Use container GetFirst & GetNext functions to set to first element, or end() if not found
   void init() 
   {
      m_Pos = 0;
      m_End = true;

      if (m_pCont && m_GetFirstFunc != 0)
      {
         m_Pos = (m_pCont->*m_GetFirstFunc)();
         advance();
      }
   }

   // Use container GetNext function to find next element in container
   void advance()
   {
      m_End = m_Pos ? false : true;
      m_Item = (m_Pos && m_pCont && m_GetNextFunc != 0) ? 
               (m_pCont->*m_GetNextFunc)(m_Pos) : Item();
   }
};

但是如果我用myCObject定义我自己的ListIter类是文件或文件夹。

But if i define my own ListIter class with myCObject being File or Folder.

class ListIter : public BaseMFCIter < myCObject, CObList  >
{
public:
   ListIter( CObList* pObj = 0) : BaseMFCIter< myCObject, CObList >
       (pObj, &CObList::GetHeadPosition, &CObList::GetNext )
   {}
};

它导致编译错误:

Error   1   error C2664: 'BaseMFCIter<Item,Cont>::BaseMFCIter(Cont *,__POSITION (__thiscall CObList::* )(void) const,myCObject (__thiscall CObList::* )(Key &) const)' : cannot convert parameter 3 from 'overloaded-function' to 'myCObject (__thiscall CObList::* )(Key &) const'

这个问题是否有重载函数的解决方法?如果有MFC集合的std :: find_if类似物,请告诉我。

Is there a workaround for this problem with overloaded function? If there is an analogue of std::find_if for MFC collections, please tell me.

推荐答案

以下是基于您提供的测试源的完整的修复示例:

Here is a complete working fixed example based on your supplied test source:

下载链接:

  • original OP code (via chat)
  • fixed code, tested on VS2010

这是相关的(已更改)代码和测试输出

struct Container : public CObList
{
    myCObject* GetNext(POSITION& rPosition)       
    {
        return dynamic_cast<myCObject*>(CObList::GetNext(rPosition)); 
    }
    myCObject const* GetNext(POSITION& rPosition) const 
    {
        return dynamic_cast<const myCObject*>(CObList::GetNext(rPosition));
    }
};


class ListIter : public BaseMFCIter < const myCObject*, Container, POSITION  >
{
public:
    ListIter( Container* pObj = 0)  
        : BaseMFCIter< const myCObject*, Container, POSITION >
            (pObj, &CObList::GetHeadPosition, &Container::GetNext)
    {
    }
};

void main( )
{
    myCObject* m = new myCObject( 1 );
    myCObject* n = new myCObject( 2 );
    myCObject* p = new myCObject( 3 );
    myCObject* q = new myCObject( 4 );

    Container cont;
    cont.AddHead( m );
    cont.AddHead( n );
    cont.AddHead( p );
    cont.AddHead( q );

    POSITION pos = cont.GetHeadPosition( );

    while (pos != NULL)
    {
        const myCObject& item = *cont.GetNext( pos );
        std::cout << "Oldfashioned: " << item.x << std::endl;
    }

    for (ListIter it=ListIter(&cont); it!= ListIter(); ++it)
    {
        std::cout << "Newfangled: " << it->x << std::endl;
    }
}

输出:

Oldfashioned: 4
Oldfashioned: 3
Oldfashioned: 2
Oldfashioned: 1
Newfangled: 4
Newfangled: 3
Newfangled: 2
Newfangled: 1

尽可能见


  • 使用 strongtyped扩展 Container 派生类访问者( todo :您可能希望添加其他 CObList :: * 界面成员,例如 GetAt(...)

  • Extended the Container derived class with strongtyped accessors (todo: you may want to add other CObList::* interface members, such as GetAt(...))

修复了 BaseMFCIter <的实例化/ code>模板来自

fixed the instantiation of BaseMFCIter template from

 BaseMFCIter < myCObject, Container, POSITION  >

 BaseMFCIter < const myCObject*, Container, POSITION  >


  • 包含STL标准样式循环到 main 演示它是否有效。

    这篇关于用于MFC容器CObList的STL迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆