This code compiles correctly.
#include <asio.hpp>
#include <memory>
#include <iostream>
struct Message { int msg; };
// never mind global variables, just for the sake of making this a minimal example
extern asio::ip::tcp::socket mysocket;
void handler(std::shared_ptr<Message> pmsg, asio::error_code error, size_t nbytes);
void readMessage()
{
std::shared_ptr<Message> pmsg{ new Message };
asio::async_read(mysocket, asio::buffer(&pmsg->msg, sizeof(int)),
[pmsg](auto err, auto nbytes) { handler(pmsg, err, nbytes); });
}
However, when I add a reference to the first argument of the handler function
void handler(std::shared_ptr<Message>& pmsg, asio::error_code error, size_t nbytes);
the code no longer compiles, complaining that I am trying to convert pmsg from a const std::shared_ptr<Message>&
to a std::shared_ptr<Message>&
.
To get it to work again, I have to introduce a const_cast<std::shared_ptr<Message>&>
in the call to the handler.
Where is the const-ness introduced?
Thanks
CodePudding user response:
psmg
is captured by value, so it is only read only inside closure. If you would it to be modifible (because handler
can do this getting shared_ptr
by reference) you have to add mutable
to lambda:
[pmsg](auto err, auto nbytes) mutable { handler(pmsg, err, nbytes); });
When pmsg
is capture by value, the compiler is allowed to make one implicit conversion, so from pmsg
is created temporary shared_ptr
instance and passed to handler
, but temporary object cannot be bound to Lvalue reference (it could be work with const lvalue ref).