Я использую boost :: bind для передачи функции-обработчика boost :: asio :: async_write. Когда я использую бесплатные функции, все работает нормально, но когда я пытаюсь переместить функции в класс, связывание приводит к ошибкам, которые я не могу расшифровать.
Я пишу некоторые данные с:
boost::asio::async_write(*socket,
boost::asio::buffer(data(),
length()),
boost::bind(handlermessagewrite,
boost::asio::placeholders::error,
this,
boost::asio::placeholders::bytes_transferred));
Затем я обрабатываю запись свободной функцией, подпись которой:
void handlermessagewrite(const boost::system::error_code& errorcode,
iodata *msg,
size_t bytes_transferred);
Это все работает, как ожидалось.
Я перемещаю обработчик внутри класса ioclient
:
class ioclient {
public:
void handlermessagewrite(const boost::system::error_code& errorcode,
iodata *msg,
size_t bytes_transferred);
}
void ioclient::handlermessagewrite(const boost::system::error_code& errorcode,
iodata *msg,
size_t bytes_transferred);
и соответственно адаптируем код boost :: bind, как видно из официальных руководств asio:
- boost::bind(handlermessagewrite,
+ boost::bind(&ioclient::handlermessagewrite,
Тем не менее, это приводит к очень непрозрачным ошибкам компиляции, чему не помогает тот факт, что одна из строк в моей IDE обрезается (code :: blocks):
\ Подталкивание \ привязывать \ bind_template.hpp | 102 | требуется от ‘boost :: _ bi :: bind_t :: result_type boost :: _ bi :: bind_t :: operator () (const A1&, const A2&) [с A1 = boost :: system :: error_code; A2 = без знака int; R = пустота; F = повышение :: _ mfi :: mf2; L = boost :: _ bi :: list3 (*) (), boost :: _ bi :: value, boost :: arg<2> (*) ()>; boost :: _ bi :: bind_t :: result_type = void] ‘|
\ Подталкивание \ ASIO \ осущ \ write.hpp | 261 | требуется от ‘void boost :: asio :: detail :: write_op :: operator () (const boost :: system :: error_code&, std :: size_t, int) [с AsyncWriteStream = boost :: asio :: basic_stream_socket; CompletionCondition = boost :: asio :: detail :: Transfer_all_t; WriteHandler = boost :: _ bi :: bind_t, boost :: _ bi :: list3 (*) (), boost :: _ bi :: va |
\ Подталкивание \ ASIO \ осущ \ write.hpp | 585 | требуется от ‘void boost :: asio :: async_write (AsyncWriteStream&Const ConstBufferSequence&, WriteHandler&&) [with AsyncWriteStream = boost :: asio :: basic_stream_socket; ConstBufferSequence = boost :: asio :: mutable_buffers_1; WriteHandler = boost :: _ bi :: bind_t, boost :: _ bi :: list3 (*) (), boost :: _ bi :: value, boost :: arg<2> (*) ()>>] ‘|
\ Iodata.cpp | 76 | требуется отсюда |
\ boost \ bind \ bind.hpp | 392 | ошибка: нет совпадения для вызова ‘(boost :: _ mfi :: mf2) (const boost :: system :: error_code&, йодата *&const без знака int&) ‘|
\ boost \ bind \ mem_fn_template.hpp | 253 | Примечание: кандидаты: |
\ boost \ bind \ mem_fn_template.hpp | 278 | примечание: R boost :: _ mfi :: mf2 :: operator () (T *, A1, A2) const [с R = void; Т = иоклиент; A1 = const boost :: system :: error_code&; A2 = йодата *] |
\ boost \ bind \ mem_fn_template.hpp | 278 | примечание: неизвестное преобразование для аргумента 1 из ‘const boost :: system :: error_code’ в ‘ioclient *’ |
\ boost \ bind \ mem_fn_template.hpp | 283 | примечание: шаблон R boost :: _ mfi :: mf2 :: operator () (U&, A1, A2) const [с U = U; R = пустота; Т = иоклиент; A1 = const boost :: system :: error_code&; A2 = йодата *] |
\ boost \ bind \ mem_fn_template.hpp | 283 | note: сбой вывода / замены аргумента шаблона: |
\ boost \ bind \ bind.hpp | 392 | примечание: невозможно преобразовать ‘(& а) -> повышение :: _ би :: :: песни2 оператор [] ((* &((boost :: _ bi :: list3 (*) (), boost :: _ bi :: value, boost :: arg<2> () ()>) это) -> boost :: _ bi :: list3 (*) (), boost :: _ bi :: value, boost :: arg<2> (*) ()> ::. Boost :: _ bi :: storage3 (*) (), boost :: _ bi :: value, boost :: arg<2> (*) ()> ::. Boost :: _ bi :: storage2 (*) (), boost ::bi :: value> :: a2)) ‘(введите’ iodata * ‘) для ввода’ const boost :: system :: |
\ boost \ bind \ mem_fn_template.hpp | 291 | примечание: шаблон R boost :: _ mfi :: mf2 :: operator () (const U&, A1, A2) const [с U = U; R = пустота; Т = иоклиент; A1 = const boost :: system :: error_code&; A2 = йодата *] |
\ boost \ bind \ mem_fn_template.hpp | 291 | примечание: не удалось вывести / заменить аргумент шаблона: |
\ boost \ bind \ bind.hpp | 392 | примечание: невозможно преобразовать ‘(& а) -> повышение :: _ би :: :: песни2 оператор [] ((* &((boost :: _ bi :: list3 (*) (), boost :: _ bi :: value, boost :: arg<2> () ()>) это) -> boost :: _ bi :: list3 (*) (), boost :: _ bi :: value, boost :: arg<2> (*) ()> ::. Boost :: _ bi :: storage3 (*) (), boost :: _ bi :: value, boost :: arg<2> (*) ()> ::. Boost :: _ bi :: storage2 (*) (), boost ::bi :: value> :: a2)) ‘(введите’ iodata * ‘) для ввода’ const boost :: system :: |
\ boost \ bind \ mem_fn_template.hpp | 299 | примечание: R boost :: _ mfi :: mf2 :: operator () (T&, A1, A2) const [с R = void; Т = иоклиент; A1 = const boost :: system :: error_code&; A2 = йодата *] |
\ boost \ bind \ mem_fn_template.hpp | 299 | примечание: неизвестное преобразование для аргумента 1 из ‘const boost :: system :: error_code’ в ‘ioclient&«|
Я убежден, что я делаю что-то не так с bind, но я не знаю, что это может быть. Есть идеи?
При использовании метода экземпляра вы должны передать this
указатель в качестве второго аргумента для bind ().
РЕДАКТИРОВАТЬ:
Я сделал то, что вы пытаетесь сделать с boost :: asio. Вот фрагмент из моей реализации:
boost::asio::async_write(
m_Socket,
boost::asio::buffer((const unsigned char *)(rMsg.c_str()), rMsg.length()),
boost::bind(&ServerToClientConnT::HandleAsioWrite,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
где HandleAsioWrite — метод, объявленный следующим образом:
void HandleAsioWrite(const boost::system::error_code& rErrorCode,
std::size_t nBytesTransferred);
Исходный пример терпит неудачу, потому что экземпляр объекта, для которого будет вызываться функция-член, не передается bind
, Это указывается в ошибке компилятора, где говорится, что нет известного преобразования из const boost::system::error_code
в ioclient*
,
Когда используешь Boost.Bind с указателями членов, это задокументировано, что
boost::bind(&X::f, args)
эквивалентноboost::bind<R>(boost::mem_fn(&X::f), args)
,
Более того, Boost.mem_fnДокументация гласит:
Это [
boost::mem_fn
] поддерживает указатели на функции-члены с более чем одним аргументом, и возвращаемый объект-функция может принимать указатель, ссылку или умный указатель на экземпляр объекта в качестве первого аргумента.
Таким образом, если этот первый аргумент boost::bind
это указатель на член, то либо:
boost::mem_fn
,boost::bind
должен быть передан дескриптор экземпляра объекта в позиции аргумента, соответствующей _1
заполнитель.Например, учитывая
struct Foo
{
void do_something(int x) {}
};
do_something
Функция-член может быть связана и вызываться с любым из следующих действий:
Foo f;
boost::bind(&Foo::do_something, &f, _1)(42); // handle is second argument.
boost::bind(&Foo::do_something, _1, _2)(&f, 42); // handle matches _1 position.
boost::bind(&Foo::do_something, _2, _1)(42, &f); // handle matches _1 position.
С Boost.Asio, boost::asio::placeholders::error
реализован как заполнитель _1
, По этой причине экземпляр объекта должен быть передан bind
Вызовите в качестве второго аргумента, или экземпляр объекта должен быть передан в качестве аргумента либо свободной функции, либо статической функции-члену, которая затем вызовет функцию-член для экземпляра объекта. Вот пример решения, которое компилируется с нестатической функцией-членом, но фрагмент интересов:
ioclient client;
iodata data;
boost::asio::async_write(
socket,
boost::asio::null_buffers(),
boost::bind(&ioclient::handlermessagewrite,
&client,
boost::asio::placeholders::error,
&data,
boost::asio::placeholders::bytes_transferred));
ошибка компилятора опубликовано в ответ на Лу указывает на то, что ioclient
функция-член пытается быть вызвана с дескриптором экземпляра iodata
несовместимый тип. За iodata
чтобы быть совместимым типом, он должен быть унаследован от ioclient
, Если это предполагаемая иерархия типов, проверьте правильность наследования. В противном случае тщательно сопоставьте типы аргументов и позиции с привязываемой функцией.