【问题标题】:C++ non-copyable lambda behaves copyable?C ++不可复制的lambda表现可复制?
【发布时间】:2019-04-12 16:48:07
【问题描述】:

为什么下面的代码会编译?

#include <memory>
#include <vector>

int main()
{
    std::vector<std::unique_ptr<int>> uncopyableStuff;
    for(int i = 0; i < 5; ++i)
        uncopyableStuff.emplace_back(std::make_unique<int>(i));
    auto lambda = [uncopyableStuff = std::move(uncopyableStuff)](){};
    static_assert(std::is_copy_constructible<decltype(lambda)>::value);
}

在我看来 lambda 是不可复制的,因为当我尝试像这样复制它时:

auto copy = lambda;

这给了我一个编译错误(如我所料)。 lambda 和复制可构造性特征是否有一些例外?

查看godbolt示例的链接: https://godbolt.org/z/GByclH

编辑:

在尝试复制时找出 lambda 是否会编译的正确方法是什么。我猜我对给定可调用对象的理论复制构造性不感兴趣,而是对成功复制构造的检测感兴趣。向量拷贝构造函数是这样定义的,我还是觉得很奇怪。

【问题讨论】:

  • std::is_copy_constructible&lt;decltype(lambda)&gt;::value 为真,因为std::vector&lt;std::unique_ptr&lt;int&gt;&gt; 有一个未删除的复制构造函数。该构造函数的主体当然是格式错误的(因为它调用了std::unique_ptr 的复制构造函数),但这超出了直接上下文,因此类型特征无法检测到它。
  • 重新“编辑”:一般情况下无法确定是否可以编译;编译器(还没有?)有任何方法可以从任意错误中“恢复”并使用 false 从您想要的测试中恢复。

标签: c++ lambda typetraits


【解决方案1】:

lambda 和复制可构造性特征是否有一些例外?

没有。如果你测试std::is_copy_constructible&lt;std::vector&lt;std::unique_ptr&lt;int&gt;&gt;&gt;::value你会发现它也是如此。

原因是std::vector 有一个可访问且不可删除的复制构造函数,即使元素类型是不可复制的。如果复制构造函数被实例化,它将无法编译,但这在直接上下文之外,因此无法被std::is_copy_constructible trait 检测到。

在元素类型的复制构造性上创建std::vectorSFINAE 的复制构造函数可能很诱人,但我相信它会破坏将类型本身的向量存储为成员的类型:struct Node { std::vector&lt;Node&gt; children; },因为在这种情况下,Nodestd::vector&lt;Node&gt; 的复制构造性将是相互依赖的。

【讨论】:

  • 这是一个有趣的问题。 SFINAE 不能用于这样的自引用。概念可以做到吗,因为它是 SFINAE 的一种合法语言版本?
猜你喜欢
  • 2019-09-20
  • 2011-03-19
  • 2012-11-21
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 2016-04-30
相关资源
最近更新 更多