这个 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 是在哪里引入的?的主要内容,如果未能解决你的问题,请参考以下文章

如何定义一个以捕获为参数的 lambda 的函数?

C++20:非类型模板参数中的非捕获 lambda

如何在标准函数 lambda c++ 11 中正确捕获参数包

如何使用lambda表达式捕获局部变量?

c ++ lambdas如何从上层范围捕获可变参数包

Lambda 捕获与参数 - 任何性能差异?