Вопрос

Эта первая часть была решена с помощью комментариев Эрика ниже, но привела к вторичной проблеме, которую я описываю после горизонтального правила.Спасибо Эрик!

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

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

Я также попробовал определить тип «type», так как думал, что моя проблема может быть как-то связана с шаблоном Sig, поскольку сам функтор является шаблонным.

Ошибка, которую я получаю:

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> > >&)’

с кучей предисловий заранее.

Заранее благодарю за любую помощь!


Хорошо, я изменил код, учитывая приведенные ниже предложения Эрика, в результате чего получился следующий код:

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

Однако это приводит к другой ошибке компиляции:

/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'

Кажется, что определив void как result_type, он теперь ожидает, что оператор() что-то вернет.Я попытался вернуть result_type из функции, но это также привело к ошибкам.Есть идеи?

Это было полезно?

Решение

Sig (или в вашем случае просто typedef void result_type; необходимо.

IIRC, лямбда::bind создает константные копии своих аргументов.

Таким образом, существует проблема с функторами с неконстантным оператором().Это решается путем создания Ftor::operator()const или обертывая (в doFtor()), _ftor с помощью boost::ref

Аналогичная проблема существует и с итераторами.Обертывание в boost::ref здесь не будет работать напрямую, поскольку в конечном итоге будет использоваться ссылка на временный объект.Более простое решение — изменить Ftor::operator(), чтобы он получал аргументы путем копирования.

Таким образом, проще всего изменить Ftor так, чтобы его оператор() был константным. и он принимает свои аргументы по копии:

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

Если вы действительно не можете сделать Ftor::operator() константным, вы можете изменить doFtor() следующим образом (но все равно необходимо заставить Ftor::operator() принимать свои аргументы путем копирования):

_threads.create_thread(bind(boost::ref(_ftor), _list.begin(), _list.end()));
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top