开发者

Boost bind function

I have a abstract base class A and a set of 10 derived classes. The infix operator is overloaded in all of the derived classes

class A{
 public:
    void printNode( std::ostream& os )
    {
           this->printNode_p();
    } 
  protected:
    virtual void printNode_p( std::ostream& os )
    {
           os << (*this);
    }
};

There is a container which stores the base class pointers. I want to use boost::bind function to call the overloaded infix operator in each of its derived class. I have written like this

std::vector<A*> m_args
....
std::ostream os;
for_each( m_args.begin(), m_args.end(), bind(&A::printNode, _1, os) );

What is the problem with this code? In visual studio i am getting an error like t开发者_开发技巧his

error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'

Thanks, Gokul.


Consider this, which works as expected:

#include <iostream>

struct base
{
    virtual ~base(void) {}

    virtual void print(std::ostream& pStream) = 0;
};

struct foo : base
{
    void print(std::ostream& pStream) { pStream << "foo" << std::endl; }
};

struct bar : base
{
    void print(std::ostream& pStream) { pStream << "bar" << std::endl; }
};

#include <boost/bind.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <algorithm>

int main(void)
{
    boost::ptr_vector<base> v;
    v.push_back(new foo);
    v.push_back(new bar);

    std::for_each(v.begin(), v.end(),
                  boost::bind(&base::print, _1, boost::ref(std::cout)));
}

First off, since you're using boost you may as well use ptr_vector to handle memory management for you. So, that's in there.

Secondly, your error is because streams are not copyable; however, boost::bind will make a copy of all it's arguments when constructing the functor. Wrap it in a boost::reference_wrapper (using the boost::ref utility function), which is copyable. When the time comes, the wrapper will convert to the necessary type and you won't notice the difference.

(This is one of the situations boost::ref was made for.)


That all said, consider using BOOST_FOREACH, which in my opinion generates the cleanest code:

#include <boost/foreach.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <algorithm>

#define foreach BOOST_FOREACH

int main(void)
{
    boost::ptr_vector<base> v;
    v.push_back(new foo);
    v.push_back(new bar);

    foreach (base* b, v)
    {
        v->print(std::cout);
    }
}


The problem was that std::ostream is not copyable. I fixed it like this

for_each( m_args.begin(), m_args.end(), bind(&A::printNode, _1, boost::ref(os) ) );

Thanks, Gokul.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜