Boost.Asio: не может использовать std :: bind() для указания обратного вызова

56
7

Я пытаюсь использовать функцию Boost.Asio async_read_until(), но у меня возникли проблемы с указанием функции-члена в качестве обратного вызова с использованием std::bind(). У меня нет проблем с использованием этой идиомы для других функций Boost.Asio, поэтому я смущен тем, почему она не работает для async_read_until().

Вот мой пример:

#include <functional>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

class Test
{
public:
boost::asio::streambuf buf;
boost::asio::ip::tcp::socket sock;

Test(boost::asio::io_service& io) :
sock(io)
{
}

void readComplete(const boost::system::error_code& error,
std::size_t bytesTransferred)
{
}

void invoke()
{
boost::asio::async_read_until(sock,
buf,
'\n',
std::bind(&Test::readComplete,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
};

int main(int argc, char** argv)
{
boost::asio::io_service io;
Test t(io);

t.invoke();

return 0;
}

В этом случае компиляция не выполняется со следующей ошибкой (наряду с другим шаблоном-компилятором-error-barf):

In file included from /home/me/eclipse-workspace/practice/main.cpp:4:
In file included from /usr/include/boost/asio.hpp:91:
In file included from /usr/include/boost/asio/read_until.hpp:921:
/usr/include/boost/asio/impl/read_until.hpp:707:3: error: static_assert failed "ReadHandler type requirements not met"
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/asio/detail/handler_type_requirements.hpp:153:3: note: expanded from macro 'BOOST_ASIO_READ_HANDLER_CHECK'
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
^
/usr/include/boost/asio/detail/handler_type_requirements.hpp:105:6: note: expanded from macro 'BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT'
static_assert(expr, msg);
^ ~~~~
/home/me/eclipse-workspace/practice/main.cpp:24:22: note: in instantiation of function template specialization 'boost::asio::async_read_until<boost::asio::basic_stream_socket<boost::asio::ip::tcp,
boost::asio::stream_socket_service<boost::asio::ip::tcp> >, std::allocator<char>, std::_Bind<std::_Mem_fn<void (Test::*)(const boost::system::error_code &, unsigned long)>
(Test *, boost::arg<1> (*)(), boost::arg<2> (*)())> >' requested here
boost::asio::async_read_until(sock,
^

Поэтому он говорит мне, что моя подпись функции ошибочна, чего, похоже, нет.

Я не понимаю, почему он не работает, и что я еще больше не понимаю, так это то, что если я просто заменю std::bind() для boost::bind(), он строит и работает полностью нормально. Может ли кто-нибудь помочь мне понять это?

FYI Я использую Boost 1.58.0 (из репозиториев Ubuntu 16.04 Universe) и clang++ 3.8 с С++ 11.

спросил(а) 2018-08-27T17:27:00+03:00 1 год, 10 месяцев назад
1
Решение
94

К сожалению, вы смешиваете и сопоставляете bind s:

std::bind(&Test::readComplete,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));

Установки boost::asio::placeholders работают только с boost::bind, а не с std::bind.

Из документов вы хотите:

std::bind(&Test::readComplete,
this,
std::placeholders::_1,
std::placeholders::_2));

или же

boost::bind(&Test::readComplete,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));

Я не понимаю, почему boost не просто говорит, что его заполнители являются std заполнителями:

namespace std {
template <int I>
struct is_placeholder<boost::arg<I>>
: integral_constant<int, I>
{ };
}

Я предполагаю, что есть веская причина?

ответил(а) 2018-08-27T17:35:00+03:00 1 год, 10 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема