3

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 this

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

Thanks, Gokul.

2
  • What is the problem you've got with this? Is it not compiling, or not doing what you want? Commented Apr 6, 2010 at 2:08
  • @Alex: I have updated the post with the error Commented Apr 6, 2010 at 2:12

2 Answers 2

5

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);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.