2

Is it somehow possible to pass an std::unique_ptr as a parameter to a boost::thread constructor? If not, what is the best workaround?

A small example:

// errors: g++ uniqueptr_thread.cpp -std=c++0x

#include <iostream>
#include <memory>
#include <boost/thread.hpp>

class TestThread{
public:
  void operator()(std::unique_ptr<int> val){
    std::cout << "parameter: " << val << std::endl;
  }

};

int main(int argc, char* argv[]){

  std::unique_ptr<int> ptr(new int(5));

  boost::thread th( new TestThread(), std::move(ptr));

}
Dutow
  • 5,638
  • 1
  • 30
  • 40

3 Answers3

2

A std::unique_ptr is, as the name suggests, unique. There can be only one!

Now, if your thread function takes a std::unique_ptr&&, and you use std::move to move the parameter in the thread function, then you can pass the std::unique_ptr. But then your copy will be empty, since you moved it to the other thread.

If std::move does not work, then your compiler or standard library may have bugs in it. I imagine that transferring ownership across threads like this isn't a common occurrence. And C++11 is still fairly new.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 1
    +1. I suspect moving it to the other thread is what he wanted. This looks like a clean way to pass an arbitrary object to a thread. – Nemo Jun 18 '11 at 19:43
  • sorry, I forgot std::move from the example code, it was there in the original, but it still won't compile – Dutow Jun 18 '11 at 19:45
2

This compiles and runs for me:

#include <iostream>
#include <memory>
#include <thread>

class TestThread{
public:
  void operator()(std::unique_ptr<int> val){
    std::cout << "parameter: " << *val << std::endl;
  }
};

int main()
{

  std::unique_ptr<int> ptr(new int(5));

  std::thread th( TestThread(), std::move(ptr));
  th.join();

}

But it has to be in C++0x mode. I don't know if the boost move emulation is good enough to do this or not.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • with which compiler? g++ 4.4.5 gives me longer error list than the boost version, using the same options (-std=c++0x) – Dutow Jun 18 '11 at 19:56
  • @Dutwo: According to C++0x, it should work. If it doesn't, then it's probably something wrong with your version of GCC or libc++. Perhaps try a more recent one? – Nicol Bolas Jun 18 '11 at 19:57
  • I used clang + libc++ (http://llvm.org/), pretty close to tip-of-development trunk for both of them, on Mac OS X. – Howard Hinnant Jun 18 '11 at 21:21
  • 1
    This does not compile in GCC4.6 either. My naive guess at the moment is that it is because `std::bind` removes references, and that there is no rvalue-reference wrapper. Indeed, using the `make_adv` construction [from this SO question](http://stackoverflow.com/questions/5126219/is-there-a-reference-wrapper-for-rvalue-references) I can make it compile, but I get a `system_error` exception at runtime. – Kerrek SB Jun 19 '11 at 16:45
  • fails to build in VS2013 – paulm Oct 29 '14 at 10:54
0

Are you sure your problem is with the unique_ptr? Why does your example use new to create your functor? That line should just read:

boost::thread th(TestThread(), std::move(ptr));
Marc
  • 408
  • 3
  • 6