Jonathan Wakely <jwakely.gcc@xxxxxxxxx> writes: | On 7 November 2011 09:51, Jonathan Wakely wrote: >> On 7 November 2011 09:26, Lars Gullik Bjønnes wrote: >>> >>> This is the wrapper I ended up with. I had to remove the throw, it >>> triggered all the time. >> >> What if you give PretendToBeCopyable a noexcept destructor? >> That should ensure the container will move it rather than copy it, >> whenever possible. > | And of course also make the copy constructor throw again, or you won't | know if the nothrow destructor made any difference or not. Making the destructor noexcept does not even compile. Below is the example code that I am toying with now, not that the copy constructor seems to never be called, probably sine vec never is resized. In my larger code, the throw triggers always. #include <iostream> #include <future> #include <thread> #include <vector> std::vector<std::function<void()>> vec; template<typename Moveable> struct PretendToBeCopyable { explicit PretendToBeCopyable(Moveable&& m) : m(std::move(m)) {} //~PretendToBeCopyable() noexcept = default; PretendToBeCopyable(PretendToBeCopyable&&) = default; PretendToBeCopyable(PretendToBeCopyable& p) : m(std::move(p.m)) { // This would never throw in this example sin vec is never // resized. // throw 5; } void operator()() { m(); } private: Moveable m; }; template<typename F> std::future<typename std::result_of<F()>::type> spawn_task(F f) { typedef typename std::result_of<F()>::type result_type; typedef std::packaged_task<result_type()> task_type; task_type task(std::move(f)); std::future<result_type> res = task.get_future(); vec.push_back(PretendToBeCopyable<task_type>(std::move(task))); std::thread([]() { auto task = std::move(vec.back()); vec.pop_back(); task(); } ).detach(); return std::move(res); } double get_res() { return 42.2; } int main() { auto f = spawn_task(get_res); std::cout << "Res = " << f.get() << std::endl; }