这个 lambda 捕获参数中的 const-ness 是在哪里引入的?

Posted

技术标签:

【中文标题】这个 lambda 捕获参数中的 const-ness 是在哪里引入的?【英文标题】:where is the const-ness in this lambda capture argument introduced? 【发布时间】:2021-11-06 09:24:02 【问题描述】:

这段代码编译正确。

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

但是,当我添加对处理函数的第一个参数的引用时

void handler(std::shared_ptr<Message>& pmsg, asio::error_code error, size_t nbytes);

代码不再编译,抱怨我试图将 pmsg 从 const std::shared_ptr&lt;Message&gt;&amp; 转换为 std::shared_ptr&lt;Message&gt;&amp;

要让它再次工作,我必须在对处理程序的调用中引入const_cast&lt;std::shared_ptr&lt;Message&gt;&amp;&gt;

const-ness 是在哪里引入的?

谢谢

【问题讨论】:

【参考方案1】:

psmg 是按值捕获的,所以它在闭包内部是只读的。如果你需要它是可修改的(因为 handler 需要它)你必须将 mutable 添加到 lambda:

[pmsg](auto err, auto nbytes) mutable  handler(pmsg, err, nbytes); );

Live demo based on BoostAsio


pmsg被值捕获时,允许编译器进行一次隐式转换,所以从pmsg创建临时shared_ptr实例并传递给handler,但临时对象不能绑定到左值引用(它可以与 const lvalue ref 一起使用)。

【讨论】:

以上是关于这个 lambda 捕获参数中的 const-ness 是在哪里引入的?的主要内容,如果未能解决你的问题,请参考以下文章