使 lambda 不可复制/不可移动

αλε*_*λυτ 3 c++ lambda

考虑以下代码

#include <iostream>
#include <thread>

int main() {
    std::thread t;
    const auto l = [x = std::move(t)]{};
    decltype(l) m = std::move(l);
}
Run Code Online (Sandbox Code Playgroud)

此代码不会编译为以下消息:

prog.cc: In function 'int main()':
prog.cc:7:32: error: use of deleted function 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)'
    7 |     decltype(l) m = std::move(l);
      |                                ^
prog.cc:6:37: note: 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)' is implicitly deleted because the default definition would be ill-formed:
    6 |     const auto l = [x = std::move(t)]{};
      |                                     ^
prog.cc:6:37: error: use of deleted function 'std::thread::thread(const std::thread&)'
In file included from prog.cc:2:
/opt/wandbox/gcc-head/include/c++/10.0.1/thread:154:5: note: declared here
  154 |     thread(const thread&) = delete;
      |     ^~~~~~
Run Code Online (Sandbox Code Playgroud)

有没有办法使 lambda 不可复制或不可移动而无需显式捕获任何不可复制的变量(即[]留空)?

Sto*_*ica 7

您可以编写一个简单的包络聚合来防止移动和复制。

struct NoCopyMove {
    NoCopyMove(NoCopyMove const&) = delete;
    NoCopyMove(NoCopyMove&&)      = delete;

    void operator=(NoCopyMove const&) = delete;
    void operator=(NoCopyMove&&)      = delete;
};

template<class Functor>
struct Fixed : Functor, NoCopyMove {
    using Functor::operator();
};

template<typename F>
Fixed (F&&) -> Fixed<std::decay_t<F>>;
Run Code Online (Sandbox Code Playgroud)

像这样使用

const auto l = Fixed{[]{}};
Run Code Online (Sandbox Code Playgroud)

NoCopyMove是一个简单的 mixin,它禁止复制和移动。以这种方式编写它允许我们保持Fixed作为简单聚合的特化。

Fixed所做的一切都是继承/初始化为基础(在可能的情况下保证复制省略)它作为参数给出的函子。然后暴露其operator().

由于没有涉及成员(除了可能在 中Functor),并且由于 lambda 不可能从我们的自定义NoCopyMove类继承,因此空基优化开始用于无状态 lambda。所以对象不会比你初始化它们的 lambda 大。