Home > front end >  where is the const-ness in this lambda capture argument introduced?
where is the const-ness in this lambda capture argument introduced?

Time:11-06

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

Live demo based on BoostAsio


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).

  • Related