0

I have a class, with attributes that I define like this:

private:
    const std::string m_ip;
    bool is_connected;
    boost::asio::io_service m_io_service;
    tcp::resolver m_resolver;
    tcp::resolver::query m_query;
    tcp::resolver::iterator m_endpoint_iterator;
    tcp::socket m_socket;

And the constructor implementations, that i define like this :

Connection::Connection(const std::string ip) 
    : m_ip(ip)
    , is_connected(false)
    , m_resolver(tcp::resolver(&m_io_service))
    , m_query(tcp::resolver::query(m_ip, "connect_back"))
    , m_endpoint_iterator(m_resolver.resolve(m_query))
    , m_socket(tcp::socket(m_io_service))
{}

Here, in the constructor, I define almost all the attributes like they need to be defined.

But I have a problem that I never had in a full .cpp file: When I define the resolver in the constructor, the compiler says that I've got an error:

/home/User/C++ Projects/Client/Network.cpp:9: error: no matching function for call to ‘boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::basic_resolver(boost::asio::io_service*)’
 Connection::Connection(const std::string ip) : m_ip(ip), is_connected(false), m_resolver(tcp::resolver(&m_io_service)), m_query(tcp::resolver::query(m_ip, "connect_back")), m_endpoint_iterator(m_resolver.resolve(m_query)), m_socket(tcp::socket(m_io_service)){
                                                                                                                ^

I don't understand why, because I use the regular things!

Any ideas?

PS : If i try to remove the & from m_io_service, i get even more errors :

/home/User/C++ Projects/Client/Network.cpp:9: error: use of deleted function ‘boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::basic_resolver(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>&&)’
Connection::Connection(const std::string ip) : m_ip(ip), 
is_connected(false), 
m_resolver(tcp::resolver(m_io_service)), 
m_query(tcp::resolver::query(m_ip, "connect_back")),
m_endpoint_iterator(m_resolver.resolve(m_query)),
m_socket(tcp::socket(m_io_service)){

AND

/usr/include/boost/asio/ip/basic_resolver.hpp:44: error: ‘boost::asio::basic_io_object<IoObjectService, Movable>::basic_io_object(const boost::asio::basic_io_object<IoObjectService, Movable>&) [with IoObjectService = boost::asio::ip::resolver_service<boost::asio::ip::tcp>; bool Movable = false]’ is private within this context

Minege
  • 37
  • 11
  • You *really* don't want one io_service per connection. They should all share the same io_service reference whose lifetime should outlive them all. Otherwise you're going to need one thread per connection, and you may as well not bother with asio... – Richard Hodges Jan 16 '17 at 21:05
  • Ok, thank for the advice. I will change my class accordingly. – Minege Jan 16 '17 at 21:08

2 Answers2

2

Adding to @Muscampester's answer, it looks like your constructor is being redundant.

Connection::Connection(const std::string ip) 
    : m_ip(ip)
    , is_connected(false)
    , m_resolver(tcp::resolver(&m_io_service))
    , m_query(tcp::resolver::query(m_ip, "connect_back"))
    , m_endpoint_iterator(m_resolver.resolve(m_query))
    , m_socket(tcp::socket(m_io_service))
{}

Should be written like this:

//I changed this to const& because, while Copy Ellision *might* optimize this, it's still 
//more semantically correct to pass by const reference.
Connection::Connection(const std::string & ip) 
    : m_ip(ip)
    , is_connected(false)
      //Note that we're no longer referring to the underlying type.
    , m_resolver(m_io_service)
    , m_query(m_ip, "connect_back")
    , m_endpoint_iterator(m_resolver.resolve(m_query))
    , m_socket(m_io_service)
{}

The difference being that your resolver, query, and socket objects are no longer being "move-constructed", and are instead being directly constructed. Based on the second error you're getting, it looks like you're using a version of boost where those objects are not movable/move-constructable (or possibly boost never intended for these types to be movable; not sure which).

If you're using an older version of boost, try updating to a later version of the library. Whether you do or don't, though, you'll need to update the code so you're no longer needlessly move-constructing.

Xirema
  • 19,889
  • 4
  • 32
  • 68
  • Good catch. That explains all the move related errors as it was only passing rvalues. – wally Jan 16 '17 at 20:31
  • @Minege You have to clarify what you mean. What 'attributes' are you trying to avoid move-constructing that haven't been taken care of by the code I showcased? – Xirema Jan 16 '17 at 20:44
  • I've the last version of Boost, and i use your showcased code, which use reference to ip, but it still not working. I do not have a problem with moving constructors, but with error: no matching function for call to ‘boost::asio::ip::basic_resolver::basic_resolver(boost::asio::io_service*)’ – Minege Jan 16 '17 at 20:50
  • @Minege I fixed the code. I forgot to remove the erroneous use of `&` to get the address of `m_io_service`, which was discussed by @Muscampester's answer. – Xirema Jan 16 '17 at 20:51
  • Ho, great ! It's working :) ! Thanks ! Now, i don't really understand why it's working better than my first code proposition. You receive the IP args by reference, you are not longer referring the underlying type, but why is this working better ? Because you directly call the constructor from the object ? Could you please give me some link about "move-construction", like you saied ? Cause it seem to be the trick ! Thanks ! – Minege Jan 16 '17 at 20:57
  • @Minege Because when you write it like `m_resolver(tcp::resolver(m_io_service))`, you're instructing the compiler to "create an anonymous resolver object, then create `m_resolver` by moving the object into the memory where `m_resolver` would be (using the move-constructor)", whereas with `m_resolver(m_io_service)`, you're instructing the compiler "create the `m_resolver` object". And the first method only works if `boost::asio::tcp::resolver` has a move-constructor, which it seemingly doesn't. [This might be useful](http://stackoverflow.com/questions/3106110/what-are-move-semantics). – Xirema Jan 16 '17 at 21:07
  • Hoooo, ok ! I understand. Thank you very much :=) – Minege Jan 16 '17 at 21:16
1

The constructor for boost::asio::ip::basic_resolver accepts the parameter by reference:

basic_resolver(boost::asio::io_service& io_service)

and you've taken the address of the variable and passed a pointer:

m_resolver(tcp::resolver(&m_io_service))

Try removing the &.

wally
  • 10,717
  • 5
  • 39
  • 72