The following program does not build in GCC 4.9.2 or clang 3.6:
#include <iostream>
#include <vector>
#include <thread>
/* Non-copyable type */
struct Foo {
Foo() {};
Foo(const Foo &) = delete;
Foo &operator=(const Foo &) = delete;
Foo(Foo &&) = default; //EDIT: This fixes CASE 1
};
/* Bar depends on Foo */
struct Bar {
Bar(const Foo &) {}
};
template <class T, class... Args>
void my_function(Args &&... args) {
std::vector<T> data;
auto lambda = [&data](Args &&... ts) { data.emplace_back(ts...); };
lambda(std::forward<Args>(args)...); // <-- Compile
std::thread(lambda, std::forward<Args>(args)...); //<--- Does NOT compile
}
int main() {
//CASE 1: (works)
// my_function<Bar>(Foo());
//CASE 2: (does not work)
Foo my_foo;
my_function<Bar>(my_foo);
}
This is because Foo is not copyable and forwarding an instance of Foo to an std:thread attempts to copy it (why?). However, if you forward the same instance to the lambda directly it compiles.
I guess, I don't fully understand all the requirements of the std::thread constructor. Any help would be greatly appreciated.
EDIT: Case 2 does not work even if we make Foo movable. Any clue?
Thanks.
http://en.cppreference.com/w/cpp/thread/thread/thread says: "First the constructor copies/moves all arguments args... to thread-accessible storage"
However, Foo is neither copyable nor movable. If you add the move constructor to Foo, then it compiles:
struct Foo {
Foo() {};
Foo(const Foo &) = delete;
Foo &operator=(const Foo &) = delete;
Foo(Foo &&) = default; // newly added
};
This does not work if you want to pass an lvalue to the thread: the thread constructor tries to copy or move the Foo object. However, Foo is not copyable, and you can't move from an lvalue (my_foo). You have these possibilities:
Turn the lvalue into an rvalue:
my_function<Bar>(std::move(my_foo));
This is dangerous, because now my_foo is in an unusable state.
Wrap the lvalue with a reference and pass the reference wrapper to the thread:
my_function<Bar>(std::cref(my_foo));
(or std::ref, if you want to modify my_foo)
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