具有宽松类型要求的C ++ 17 lambda捕获

Daw*_*ski 8 c++ lambda c++14 c++17

我有以下代码,可以用C ++ 17编译器编译,但不能用C ++ 14编译。我想知道发生了什么变化,从而允许以下代码进行编译:

struct Foo{
  Foo()=default;
  Foo(const Foo&)=default;// copy by const ref 
};

struct Bar{
  Bar()=default;  
  Bar(Bar&)=default; //copy by non const
};

int main()
{
  Foo foo;
  Bar bar;
  Bar barcpy = bar;
  auto foolam = [foo]{};
  auto barlam = [bar]{}; //compiles only with C++17
}
Run Code Online (Sandbox Code Playgroud)

是否有任何确切的建议可以编译此代码,或者是通过其他功能实现的?

Bar*_*rry 8

保证复制消除(带措辞)。这里的lambda实际上是一条红鲱鱼。

在C ++ 14中,这是:

auto barlam = [bar]{};
Run Code Online (Sandbox Code Playgroud)

仍然要求移动构造有效(即使您不希望移动并且该移动很可能也会被忽略)。但是该lambda并不是可移动构造的,因为Bar它不是可移动构造的。Foo 是可移动构造的,因此foolam效果很好。

非lambda版本是:

auto bar = Bar{}; // error in C++14
auto foo = Foo{}; // ok
Run Code Online (Sandbox Code Playgroud)

在C ++ 17中,这不是移动构造-我们只是直接初始化目标对象。从某种意义上说,我们正在阻止这一行动。从不同的意义上说,语言规则实际上根本没有动静。所以这:

auto bar = Bar{};
Run Code Online (Sandbox Code Playgroud)

完全等同于:

Bar bar{};
Run Code Online (Sandbox Code Playgroud)

对于lambda也是如此。