Consider the following code:
#include <iostream>
#include <thread>
int main() {
std::thread t;
const auto l = [x = std::move(t)]{};
decltype(l) m = std::move(l);
}
This code doesn't compile with the following messages:
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; | ^~~~~~
Is there a way to make lambda non-copyable or non-movable without explicit capturing an any non-copyable variable (i.e. leaving [] empty)?
You can write a simple enveloping aggregate that will prevent the move and copy.
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>>;
To be used like this
const auto l = Fixed{[]{}};
NoCopyMove is a simple mixin that disables copying and moving. Writing it this way allows us to keep the specializations of Fixed as simple aggregates.
All Fixed does is inherit/initialize as base (with guaranteed copy elision when possible) the functor it's being given as an argument. And then expose its operator().
Since there are no members involved (other then maybe in Functor), and since a lambda cannot possibly inherit from our custom NoCopyMove class, the empty base optimization kicks in for stateless lambdas. So objects are not expected to be any larger than the lambda you initialize them with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With