Pergunta

Esta primeira peça foi resolvida pelos comentários de Eric abaixo, mas levou a uma questão secundária que descrevo após a regra horizontal. Obrigado Eric!

Estou tentando passar por um functor que é uma classe modelada para o método create_thread da classe Boost Thread_group, juntamente com dois parâmetros para o functor. No entanto, não consigo ir além do meu erro de compilação atual. Com o código abaixo:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/thread.hpp>
#include <vector>

using namespace boost::lambda;
using namespace std;

namespace bl = boost::lambda;

template<typename ftor, typename data>
class Foo
{
public:
    explicit Foo()
    {
    }
    void doFtor ()
    {
        _threads.create_thread(bind(&Foo<ftor, data>::_ftor, _list.begin(), _list.end()));
        //_threads.create_thread(bind(_ftor, _list.begin(), _list.end()));
        _threads.join_all();
    }

private:
    boost::thread_group _threads;
    ftor _ftor;
    vector<data> _list;
};

template<typename data>
class Ftor
{
public:
    //template <class Args> struct sig { typedef void type; }

    explicit Ftor () {}

    void operator() (typename vector<data>::iterator &startItr, typename vector<data>::iterator &endItr)
    {
        for_each(startItr, endItr, cout << bl::_1 << constant("."));
    }
}

Eu também tentei o 'Type' typedef-ing, pois pensei que meu problema poderia ter algo a ver com o modelo SIG, pois o próprio functor é modificado.

O erro que estou recebendo é:

error: no matching function for call to ‘boost::lambda::function_adaptor<Ftor<int> Foo<Ftor<int>, int>::*>::apply(Ftor<int> Foo<Ftor<int>, int>::* const&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int>> >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)’

com um monte de preâmbulo antes.

Agradecemos antecipadamente por qualquer ajuda!


Ok, eu modifiquei o código das sugestões de Eric abaixo, resultando no seguinte código:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/thread.hpp>
#include <vector>

using namespace boost::lambda;
using namespace std;

namespace bl = boost::lambda;

template<typename ftor, typename data>
class Foo
{
public:
    explicit Foo()
    {
    }
    void doFtor ()
    {
        _threads.create_thread(bl::bind(boost::ref(_ftor), _list.begin(), _list.end()));
        _threads.join_all();
    }

private:
    boost::thread_group _threads;
    ftor _ftor;
    vector<data> _list;
};

template<typename data>
class Ftor
{
public:
    typedef void result_type;

    explicit Ftor () {}

    result_type operator() (typename vector<data>::iterator &startItr, typename vector<data>::iterator &endItr)
    {
        for_each(startItr, endItr, cout << bl::_1 << constant("."));
        return ;
    }
};

No entanto, isso resulta em outro erro de compilação:

/usr/local/include/boost/lambda/detail/function_adaptors.hpp:45: error: no match for call to ‘(Ftor<int>) (const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)’
ftor.h:41: note: candidates are: void Ftor<data>::operator()(typename std::vector<data, std::allocator<_CharT> >::iterator&, typename std::vector<data, std::allocator<_CharT> >::iterator&) [with data = int]
/usr/local/include/boost/lambda/detail/function_adaptors.hpp:45: error: return-statement with a value, in function returning 'void'

Parece que, tendo definido o vazio como resultado_type, agora espera que o operador () retorne algo. Tentei devolver o resultado_type de dentro da função, mas isso também gerou erros. Alguma ideia?

Foi útil?

Solução

Sig (ou no seu caso, simplesmente typedef void result_type; é necessário.

IIRC, Lambda :: bind faz cópias constantes de seus argumentos.

Portanto, existe um problema com os funções com o operador não-consalte (). Isso é resolvido fazendo ftor :: operator () const ou Ao embrulhar (em Doftor ()), _ftor com Boost :: Ref

Há um problema semelhante com os iteradores. O embrulho no Boost :: Ref, aqui não funcionará diretamente porque acabaria usando uma referência a um temporário. A solução mais simples é modificar o ftor :: operator () para assumir seus argumentos por cópia.

O mais simples é modificar o FTOR para que seu operador () seja const e Ele leva seus argumentos por cópia:

void operator() (typename vector<data>::iterator startItr, typename vector<data>::iterator endItr)const

Se você realmente não pode fazer o FTOR :: Operator () const, pode modificar o DOFTOR () da seguinte maneira (mas ainda é necessário fazer o ftor :: operator () assumir seus argumentos por cópia):

_threads.create_thread(bind(boost::ref(_ftor), _list.begin(), _list.end()));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top