find_if在MFC容器中,迭代器派生自std :: iterator [英] find_if in MFC container with iterator derived from 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 _wheneverstring ::比较
) - 您搜索的1不存在
- 因为谓词不正确,您收到了第一个匹配是第一个元素,也插入了最后一个,名称为
four
:) - 找到有效的匹配(取消引用结束迭代器是非法的,可能导致您的程序崩溃,或者执行更糟糕的操作:
- )
x.c_str )
在输出语句中 -
我改变了
比较
谓词更加惯用:
(bool) lhs->x.compare( stringToCompare )
returns true _whenever the string don't match** (seestring::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()
aconst
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屋!