C++ 如果std::函数捕获了唯一的\u ptr,那么如何复制它? #包括 #包括 #包括 结构PacketFrom { typedef std::unique_ptr SPtr; }; 模板 R类{ 公众: 无效队列读取(P*t) { doSomething([t=typename PacketFrom::SPtr(t)]({test(std::move(t));}); } 无效剂量测量(标准::函数f){ } 无效测试(包装发件人::SPtr p){ } }; int main() { R; 返回0; }

C++ 如果std::函数捕获了唯一的\u ptr,那么如何复制它? #包括 #包括 #包括 结构PacketFrom { typedef std::unique_ptr SPtr; }; 模板 R类{ 公众: 无效队列读取(P*t) { doSomething([t=typename PacketFrom::SPtr(t)]({test(std::move(t));}); } 无效剂量测量(标准::函数f){ } 无效测试(包装发件人::SPtr p){ } }; int main() { R; 返回0; },c++,C++,如果lambda函数是通过copy传递的,那么该代码如何工作?lambda拥有一个不可复制的唯一\u ptr。我认为它只是没有捕获唯一的ptr,所以我添加了test(),以确保它正在捕获。但是,代码编译得很好。从这个意义上说,这段代码实际上不“工作”。它可以编译,但这只是因为您从未调用queue\u read 如果您尝试使用它(这迫使编译器实际实例化R::queue\u read,直到那时它才需要执行此操作),那么每个编译器都会出现一个错误: #include <iostream>

如果lambda函数是通过copy传递的,那么该代码如何工作?lambda拥有一个不可复制的
唯一\u ptr
。我认为它只是没有捕获唯一的ptr,所以我添加了
test()
,以确保它正在捕获。但是,代码编译得很好。

从这个意义上说,这段代码实际上不“工作”。它可以编译,但这只是因为您从未调用
queue\u read

如果您尝试使用它(这迫使编译器实际实例化
R::queue\u read
,直到那时它才需要执行此操作),那么每个编译器都会出现一个错误:

#include <iostream>
#include <memory>
#include <functional>

struct PacketFrom
{
    typedef std::unique_ptr<PacketFrom> SPtr;
};

template<class P> 
class R{
    public:
    void queue_read(P *t)
    {
        doSomething([t = typename PacketFrom::SPtr(t)](){test(std::move(t));});
    }

    void doSomething(std::function<void()> f) {

    }

    void test(PacketFrom::SPtr p) {

    }
};

int main()
{
    R<PacketFrom> r;

    return 0;
}
模板
R类{
公众:
无效队列读取(P*t)
{
剂量测定法([this,t=std::unique_ptr

(t)](){test(std::move(t));}); } 无效剂量测量(标准::函数f){ (f)无效; } 无效试验(标准:唯一性试验

P){ (无效)p; } }; int main() { R; r、 队列读取(新整数(1)); 返回0; }

clang 9.0:

错误:调用“std::unique\u ptr”的已删除构造函数
剂量测定法([this,t=std::unique_ptr

(t)](){test(std::move(t));});

gcc 9.2:

错误:使用已删除函数“std::unique\u ptr::unique\u ptr(const std::unique\u ptr&)[带_Tp=int;_Dp=std::default\u delete]”
11 |剂量测定法([this,t=std::unique_ptr

(t)]({test(std::move(t));});

MSVC 19.22:

错误C2280:'std::unique_ptr::unique_ptr(const std::unique_ptr&'):尝试引用已删除的函数
(谢谢Richard!)

同样,这里的关键是编译器实际上没有编译
queue\u read
的代码,因为没有必要。由于在类主体中定义,函数是隐式
内联的
。为某些
P
实例化
R

只会实例化声明,而不会实例化其成员函数的定义。只有当您真正调用
queue\u read
时,编译器才会抱怨

顺便说一句,这是件好事。您可以使用
std::vector
并执行所有不需要复制的操作,即使某些
std::vector
成员函数需要可复制类型。但只要不使用后面的函数,一切都很好。如果编译器总是实例化所有的成员函数定义并报告其中的错误(即使从未使用过),这将是非常麻烦的

如果std::函数捕获了唯一的\u ptr,那么如何复制它

std::function
不会捕获任何内容

捕获不可复制对象(如
std::unique_ptr
)的lambda本身是不可复制的。这样的lambda不满足,任何其他不可复制的函数对象类型也不满足要求函子可复制的
std::function
的要求。标准规则(来自最新草案):

[func.wrap.func.con]

error C2280: 'std::unique_ptr<P,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
模板函数(F);
要求:F应可施工


然而,代码编译得很好


当格式错误的函数是模板的未使用函数时,这是典型的。如果您试图调用该函数,它将无法编译。

此处未复制任何内容
f
是根据
queue\u read
中的lambda表达式构造的。但它仍然不应该起作用,因为在
doSomething
中,您不再知道
f
无法复制;G++和MSVC编译:建议[语言律师] TAG始终记住C++有这种独特的失败模式,在这里询问编译器“这是一个有效程序”有错误的正误…<代码>(t)](({测试(STD::移动(t));});<代码>有这么多()()({][][}}[[]]{]])是正常的吗((C++中没有空格)你知道为什么相同的代码在这里工作吗?我已经从这里写过我的问题,但是它不起作用。works@GuerlandoOCs如果你给我链接到类
TunIO
的实例化,我可以看一下,但是我没有时间去挖掘一些实例化和cla的定义我自己在那里用作
TunIO
的模板参数。@GuerlandoOCs
async\u read\u some
不接受
std::function
而是
HANDLER&
,其中
HANDLER
是一个模板类型。换句话说,这里没有什么可看的:lambda被移动到函数中。@GuerlandoOCs没有相同的代码t这里。我既看不到
std::unique\u ptr
也看不到
std::function
@GuerlandoOCs No。每个lambda都有一个唯一的、不可命名的类型。这就是模板参数将具有的类型。可以将其视为
struct\u SOME\u HASH\uuu{auto operator()(/*您的参数*/){/*您的代码*/};/*您的捕获*/}
-在较高的层次上。如果
std::function
不存在,lambda将像现在一样工作(但接受将lambda捕获到非模板方法中基本上需要
std::function
重新实现)。lambda不是
std::function
,不会自动“衰减”到它们(但可以无缝转换为它们)。
error: call to deleted constructor of 'std::unique_ptr<int>'
    doSomething([this, t = std::unique_ptr<P>(t)]() { test(std::move(t)); });
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'
11 |         doSomething([this, t = std::unique_ptr<P>(t)]() { test(std::move(t)); });
error C2280: 'std::unique_ptr<P,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
template<class F> function(F f);