开发者

operators on Iterators in C++

I am porting an old code base to OSX.

I have the following snippet of code:

FxLayerList::iterator lastVisible = NULL;
for (FxLayerList::iterator iter = mBranch.begin(); iter != mBranch.end(); iter++) {
    if ( (*iter)->IsVisible() && !(*iter)->IsBypass()) {
        lastVisible = iter;
    }
}
if (lastVisible != NULL && (*lastVisible)->GetGeneratedImage()) {

I get an error that says: error: no match for 'operator!=' in 'lastVisible != 0'

I dont follow, I thought operations like != and ==, etc were standard operations. Why the complaint from the compiler?

UPDATE: I am trying to understand the comparison of objects. What if the code is like this:

FxBool FxLayerList::Contains(FxLayer *layer) const
{
for (FxLayerList::const_iterator iter=this->begin(); iter != this->end(); iter++)
{
    if ((*iter) == layer) {
        return true;
开发者_StackOverflow社区    }   
}
return false;
}

with errors like: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:

What is the core concept I am missing?

Update 2:

// FxSmartPtr is a smart pointer that is also typed for each class, avoiding the need for any casting.
// Setting an FxSmartPtr to NULL actually kills the memory that it's pointing to as well.
template <class eachClass>
class FxSmartPtr
{
public:
// Construction

// Default constructor makes an empty container.
FxSmartPtr(void) : mPtr(NULL) {}

// Construction with a ptr adds one reference to it.
FxSmartPtr(eachClass *ptr) : mPtr(ptr) { this->Reference(); }

// Copy construction means that both smart pointers end up with a reference to the object.
FxSmartPtr(const FxSmartPtr & inPtr) :mPtr(NULL) { FrAssignRef(mPtr,(eachClass *)inPtr.mPtr); }

// Default construction
FxSmartPtr(FxConstructArg cons) { if (cons == FcNew) mPtr = new eachClass(); }
FxSmartPtr(FxConstructArg cons,eachClass *ptr) { if (cons == FcNew) mPtr = ptr; }

// Destructor removes only the one reference that we own.
~FxSmartPtr() { this->Dispose(); }


// Most important and common use is via assignment. References are always safely balanced.

// AssignReference safely replaces one reference counted ptr with another. 
static inline eachClass * FrAssignRef(eachClass *& to, eachClass * from)
    { if (from) from->AddReference(); if (to) to->RemoveReference(); to = from; return to; }

// If you assign a pointer to this object we add one reference count to it.
const FxSmartPtr<eachClass> & operator = (const eachClass *ptr)
    { FrAssignRef(mPtr,(eachClass *)ptr); return *this; }

// Replace our referenced object with a reference added to the incoming one.
const FxSmartPtr<eachClass> & operator = (const FxSmartPtr & inPtr)
    { FrAssignRef(mPtr,(eachClass *)inPtr.mPtr); return *this; }

// Assignment to a dumb pointer takes/gives no references.
operator eachClass * (void) const
    { return mPtr; }
eachClass * operator->(void)
    { if (mPtr != NULL) if (mPtr->GetRefCount() < 1 || mPtr->GetRefCount() > 10000) ASSERT(0); return mPtr; }
const eachClass * operator->(void) const
    { if (mPtr != NULL) if (mPtr->GetRefCount() < 1 || mPtr->GetRefCount() > 10000) ASSERT(0); return mPtr; }


// Explicit assignment and object transfers

// Get() - return ptr with no reference
eachClass * Get(void) const
    { return mPtr; }
eachClass * GetPtr(void)
    { return mPtr; }

// Own() - return ownership with ptr
eachClass * Own(void)
    { if (mPtr) mPtr->AddReference(); return mPtr; }

// Set() - we take our own reference on your object
FxSmartPtr<eachClass> & Set(eachClass * ptr)
    { FrAssignRef(mPtr, ptr); return *this; }

// Take() - you give us your reference
FxSmartPtr<eachClass> & Take(eachClass * ptr)
    { FrDispose(mPtr); mPtr = ptr; return *this; }


// Comparison operators compare the pointers contained in each
FxBool operator == (const FxSmartPtr & inPtr) const
    { return (mPtr == inPtr.mPtr); }
FxBool operator == (const eachClass * inPtr) const
    { return (mPtr == inPtr); }
FxBool operator != (const FxSmartPtr & inPtr) const
    { return (mPtr != inPtr.mPtr); }
FxBool operator != (const eachClass * inPtr) const
    { return (mPtr != inPtr); }

// Reference() and Dispose() change the normal reference count. If you use these then
// you end up having to count references externally.

// Safely take a reference if the ptr is not nil
void Reference(void) { if (mPtr != NULL) mPtr->AddReference(); }
// Safely dispose one reference count.
void Dispose(void) { if (mPtr != NULL)
    // JASON/INDIE - SLACKMOEHRLE@GMAIL.COM
    // { ULONG refs = mPtr->GetRefCount(); mPtr->RemoveReference(); if (refs <= 1) mPtr = NULL; } }
    { FxUInt32 refs = mPtr->GetRefCount(); mPtr->RemoveReference(); if (refs <= 1) mPtr = NULL; } }

protected:

    eachClass *mPtr;
};


It looks that lastVisible is an object rather than just a pointer. If you compare some object with something, then it has to have the appropriate operator.

Maybe this would compile?

FxLayerList::iterator lastVisible = mBranch.end();
for (FxLayerList::iterator iter = mBranch.begin(); iter != mBranch.end(); iter++)
{
    if ( (*iter)->IsVisible() && !(*iter)->IsBypass())
    {
       lastVisible = iter;
    }
}
if (lastVisible != mBranch.end() && (*lastVisible)->GetGeneratedImage())
{ ...

Or if FxLayerList is just a collection of pointers to FxLayer, this would be more straightforward:

FxLayer *lastVisible = NULL;
for (FxLayerList::iterator iter = mBranch.begin(); iter != mBranch.end(); iter++)
{
    if ( (*iter)->IsVisible() && !(*iter)->IsBypass())
    {
        lastVisible = *iter;
    }
}
if (lastVisible != NULL && lastVisible->GetGeneratedImage())
{ ...

Answer to UPDATE: see my comment below. The problem (compiler error message) can be solved by explicitly retrieving the pointer from the "smart" pointer:

FxBool FxLayerList::Contains(FxLayer *layer) const
{
    for (FxLayerList::const_iterator iter=this->begin(); iter != this->end(); iter++)
    {
        if (iter.Get() == layer) {
            return true;
        }   
    }
    return false;
}


The standard operators are overloadable to support directly comparing objects, but out of the box they wouldn't know what to compare (I think the default behaviour would be to simply compare the object's address, but your error seems to contradict that).

In any event, How to compare two objects (the calling object and the parameter) in a class? seems to be a very similar problem.

Within your class you should probably add in something like what Alexander suggested above:

int Date :: Compare (const Date& d) {

  if (year<d.year) {
    return -1;
  }
}

bool operator == (const Date& d) const {
   return !Compare(d);
}

Of course modified to suit your comparison requirements.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜