开发者

boost::ptr_vector and find_if

I have a class:

//header f开发者_如何学JAVAile
class CMDatabase
{
    class Try;
    typedef boost::shared_ptr<Try> TryPtr;
    typedef boost::ptr_vector<Try> TryVector;
    typedef TryVector::iterator TryVectorIterator;

    class Try
    {
        public:
            virtual ~Try();
            virtual bool equal(CMDatabase::TryPtr mySd) = 0;
    };
};

//.cpp file

class TryImpl : public CMDatabase::Try
{
    bool equal(CMDatabase::TryPtr mySd)
    {
        //boost::shared_ptr<ServiceDataImpl> ServiceDataImplPtr;
        //const ServiceDataImplPtr pOtherData = dynamic_cast<const ServiceDataImplPtr>(mySd);

        //ServiceDataImpl *pOtherData = dynamic_cast<ServiceDataImpl *>(mySd.get());
        return true;
    }
};

//Another .cpp file

void UpdateClass::TryFind()
{
    CMDatabase::TryVector defaultTry;
    CMDatabase::TryVector updateTry;

//Code for filling two vectors here....

    for(CMDatabase::TryVectorIterator i = defaultTry.begin(); i != defaultTry.end(); ++i)
    {
       CMDatabase::TryVectorIterator it = find_if(updateTry.begin(), updateTry.end(),bind1st(mem_fun(&CMDatabase::Try::equal), *i));

    }
}

When I compile this, I get error:

Error 1 error C2440: 'initializing' :

cannot convert from 'const CMDatabase::Try' to 'CMDatabase::Try

*' c:\program files\microsoft visual studio 9.0\vc\include\functional 296

Can anyone pelase tell me what is it that I am doing wrong and how to correct it.


The issue is that your equal method is not const qualified.

class Try
{
public:
  virtual ~Try();
  virtual bool equal(CMDatabase::TryPtr const& mySd) const = 0;
};

bool TryImpl::equal(CMDatabase::TryPtr const& mySd) const { return true; }

Note:

  • the const added to the method, otherwise it cannot be used on const objects
  • the const added on the pointer: copying shared_ptr does cost, because it necessitates incremented a shared counter, and decrementing it afterward.

EDIT:

Reminder for the unwary: the Pointer Container library has been designed so that the interface would be as easy to use a possible, and one of the goody is that you don't have to double dereference. This compiles:

 boost::ptr_vector<int> vec;
 vec.push_back(new int(3));

 int& i = *vec.begin();

Thus, your functor must take a reference, not a pointer :)


Just for sake of completeness, the following statement is wrong! Thanks to Matthieu M. to point out my mistake!

On dereferencing an iterator of the boost pointer container you will get the pure pointer to the element. So you can try to dereference the pure pointer you get through the iterator:

CMDatabase::TryVectorIterator it =
  find_if(updateTry.begin(), updateTry.end(), bind1st(mem_fun(&CMDatabase::Try::equal), **i));

Where the following is still correct ;)

Or you can use the the operator[] implementation of the boost::ptr_vector which will return a reference to the element:

for (std::size_t i = 0, l = ; defaultTry.size(); ++i) {
  CMDatabase::TryVectorIterator it = std::find_if(
    updateTry.begin(),
    updateTry.end(),
    std::bind1st(std::mem_fun(&CMDatabase::Try::equal), defaultTry[i])
  );
}

Hope this helps.


Sorry, For soem reason, i could not add comment to previous post, so I am writing it as answer.

I tried both the methods. First one gives, illegal indirection.

And for the second one, it gives the same error: In verbose output, the details are as follows:

c:\program files\microsoft visual studio 9.0\vc\include\functional(296) : error C2440: 'initializing' : cannot convert from 'const CMDatabase::Try' to 'CMDatabase::Try *' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called c:\fta_chk\tools\channel_editor\ivodb\channellistupdate.cpp(103) : see reference to function template instantiation 'std::binder1st<_Fn2> std::bind1st,CMDatabase::Try>(const _Fn2 &,const _Ty &)' being compiled with [ _Fn2=std::mem_fun1_t, _Result=bool, _Ty=CMDatabase::Try, _Arg=CMDatabase::TryPtr ]

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜