Функция Boost Bind - PullRequest
       17

Функция Boost Bind

3 голосов
/ 06 апреля 2010

У меня есть абстрактный базовый класс A и набор из 10 производных классов. Инфиксный оператор перегружен во всех производных классах

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

Существует контейнер, в котором хранятся указатели базового класса. Я хочу использовать функцию boost :: bind для вызова перегруженного инфиксного оператора в каждом из его производных классов. Я написал так

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

В чем проблема с этим кодом? В визуальной студии я получаю сообщение об ошибке, подобное этому

ошибка C2248: 'СТД :: basic_ios <_Elem, _Traits> :: basic_ios' : не может получить доступ к приватному члену объявлен в классе 'СТД :: basic_ios <_Elem, _Traits>'

Спасибо, Gokul.

Ответы [ 2 ]

5 голосов
/ 06 апреля 2010

Рассмотрим, что работает как ожидалось:

#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)));
}

Прежде всего, поскольку вы используете boost, вы также можете использовать ptr_vector для управления памятью. Итак, это там.

Во-вторых, ваша ошибка в том, что потоки не могут быть скопированы ; однако boost::bind сделает копию всех своих аргументов при создании функтора. Оберните его в boost::reference_wrapper (используя служебную функцию boost::ref), который можно скопировать. Когда придет время, оболочка преобразуется в нужный тип, и вы не заметите разницу.

(Это одна из ситуаций, для которой была создана boost::ref.)


Несмотря на это, рассмотрите возможность использования BOOST_FOREACH, который, по моему мнению, генерирует самый чистый код:

#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);
    }
}
0 голосов
/ 06 апреля 2010

Проблема была в том, что std :: ostream не копируется. Я исправил это так

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

Спасибо, Gokul.

...