3

I'm trying to use Boost.Asio's async_read_until() free function, but I'm having trouble specifying a member function as the callback using std::bind(). I have no trouble using this idiom for other Boost.Asio functions, so I'm confused as to why it's not working for async_read_until().

Here's my example:

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

In this case, the compilation fails with the following error (along with other template-compiler-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,
                     ^

So it's telling me that my function signature is wrong, which it doesn't appear to be.

I don't understand why it's not working, and what I more so don't understand is that if I just swap out std::bind() for boost::bind(), it builds and works completely fine. Could someone please help me understand this?

FYI I'm using Boost 1.58.0 (from the Ubuntu 16.04 Universe repos) and clang++ 3.8 with C++11.

2
  • i think you need to use boost::bind Commented Aug 27, 2018 at 14:35
  • use boost::bind instead of std::bind, or use std::placeholders::_1 and std::placeholderds::_2 or use Asio instead of it's Boost version Commented Aug 27, 2018 at 14:36

1 Answer 1

7

Unfortunately, you're mixing and matching binds:

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

The boost::asio::placeholders only work with boost::bind, not with std::bind.

From the docs, you want either:

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

or

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

I don't understand why boost doesn't just say that its placeholders are std placeholders:

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

I assume there's a good reason?

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.