find_if在MFC容器中,迭代器派生自std :: iterator [英] find_if in MFC container with iterator derived from std::iterator

查看:177
本文介绍了find_if在MFC容器中,迭代器派生自std :: iterator的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 工作迭代器 MFC CObList - BaseMFCIter 。它的工作循环循环,但我仍然没有设法使 ListIter 使用STL算法find_if正常工作。
代码

I have a working iterator for MFC CObList - BaseMFCIter. It works for iterating in loop but i still didn't managed to make ListIter to work properly with STL algorithm find_if. Code

#include < iterator >
#include "afxwin.h"
#include "afxtempl.h"
#include <iostream>
#include <algorithm>
#include <cstdlib> 
class myCObject : public CObject
{
public:
    myCObject( std::string val )
    {
        x = val;
    }
    std::string x;
};
template < typename 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();
    }
};
    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)
        {
        }
    };

    struct Comparator
    {
        std::string stringToCompare;
        bool operator() ( const myCObject* lhs )
        {
            return (bool) lhs->x.compare( stringToCompare );
        }
    };

    void main( )
    {


        myCObject* m = new myCObject( "one" );
        myCObject* n = new myCObject( "two" );
        myCObject* p = new myCObject( "three" );
        myCObject* q = new myCObject( "four" );

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

        Comparator pred;
        pred.stringToCompare = "1";
        ListIter iter = ListIter( &cont );
        ListIter endIter = ListIter( );
        ListIter foundIter = std::find_if( iter, endIter, pred );

        std::cout << "foundIter x is: " << foundIter->x.c_str() << std::endl;

    }

给我 foundIter x is:四。这是因为定义结束位置的方式。

gives me foundIter x is: four. This propably happens because of the way the end position is defined so

_InIt _Find_if(_InIt _First, _InIt _Last, _Pr _Pred)
    {   // find first satisfying _Pred
    _DEBUG_RANGE(_First, _Last);
    _DEBUG_POINTER(_Pred);
    for (; _First != _Last; ++_First)
        if (_Pred(*_First))
            break;
    return (_First);
    }

不能正确迭代,但我无法弄清楚如何修复。

doesn't iterate properly but i can't figure out how to fix it.

推荐答案

修正了一些问题:


  • (bool)lhs-> x.compare(stringToCompare)返回True _whenever string ::比较

  • 您搜索的1不存在

  • 因为谓词不正确,您收到了第一个匹配是第一个元素,也插入了最后一个,名称为four:)

  • 找到有效的匹配(取消引用结束迭代器是非法的,可能导致您的程序崩溃,或者执行更糟糕的操作:

  • x.c_str )在输出语句中

  • 我改变了比较谓词更加惯用:

  • (bool) lhs->x.compare( stringToCompare ) returns true _whenever the string don't match** (see string::compare)
  • you were searching for "1", which doesn't exist
  • since the predicate was wrong, you received the first match, which was the first element, also inserted the last, and the name was "four" :)
  • you didn't check whether a valid match was found (dereferencing the end-iterator is illegal and may crash your program or do worse things: undefined behaviour)
  • you had a superflous x.c_str() in the output statement
  • I changed the Compare predicate around to be more idiomatic:


  • 从构造函数初始化 stringToCompare >使运算符(

  • c $ c> const 方法

  • initialize stringToCompare from the constructor
  • make the field const
  • make the operator() a const method

>

回到家后,我终于打破了调试器来跟踪这个奇怪的行为(见注释)。

After arriving home, I finally broke out the debugger to track that strange behaviour (see comments).

令我失望的是,我发现 BaseMFCIter 是由对迭代器的理解非常有限的人设计的 复制构造函数和赋值运算符完全错误:它们创建了一个新的 begin 迭代器 - 为同一集合。然而,这意味着迭代器永远不能从函数返回。

To my dismay, I found out that the BaseMFCIter was designed by someone with very limited understanding of what an iterator is: the copy constructor and assignment operator were completely wrong: they had the effect of creating a new begin iterator - for the same collection. This however, means that an iterator could never be returned from a function.

因此,我修复它(首先通过实现它,然后通过删除现在冗余的构造函数和operator =赞成编译器生成的默认实现)。

Therefore, I fixed it (first by implementing it right, later by removing the now-redundant constructor and operator= in favour of the compiler-generated default implementations).

git clone git://gist.github.com/1353471.git




  • 分钟前依赖于默认生成的副本构造函数和分配

  • sehe 12分钟前fixed broken copy constructor and assignment

  • li>


  • > sehe 25小时前( MFC容器CObList的STL迭代器

    • sehe 11 minutes ago rely on default generated copy constructor and assignment instead
    • sehe 12 minutes ago fixed broken copy constructor and assignment
    • sehe 65 minutes ago tentative
    • Dmitry 73 minutes ago Attempt at find_if with predicate
    • sehe Heeren 25 hours ago Fixed and Tested (VS2010)
    • sehe 25 hours ago ( STL iterator for MFC container CObList )
    •  

      #include "afxwin.h"
      #include "afxtempl.h"
      #include <iostream>
      #include <algorithm>
      #include <cstdlib> 
      #include <string>
      #include <iterator>
      
      class myCObject : public CObject
      {
      public:
          myCObject( const std::string& val ) { x = val; }
          std::string x;
      };
      
      template < typename 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(); }
      
          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();
          }
      };
      
      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)
          {
          }
      };
      
      struct Comparator
      {
          Comparator(const std::string& compareTo) : stringToCompare(compareTo) {}
      
          bool operator() ( const myCObject* lhs ) const
          {
              return 0 == lhs->x.compare( stringToCompare );
          }
        private:
          const std::string stringToCompare;
      };
      
      void main( )
      {
          myCObject* m = new myCObject( "one" );
          myCObject* n = new myCObject( "two" );
          myCObject* p = new myCObject( "three" );
          myCObject* q = new myCObject( "four" );
      
          Container cont;
          cont.AddHead( m );
          cont.AddHead( n );
          cont.AddHead( p );
          cont.AddHead( q );
      
          Comparator pred("three");
          ListIter iter = ListIter(&cont),
                   endIter = ListIter( );
      
          ListIter foundIter = std::find_if( iter, endIter, pred );
      
          if (endIter != foundIter)
          {
              std::cout << "foundIter x is: " << foundIter->x << std::endl;
          }
          else
          {
              std::cout << "not found" << std::endl;
          }
      }
      

      这篇关于find_if在MFC容器中,迭代器派生自std :: iterator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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