Search code examples
multithreadingvisual-studio-2012c++11initializationstdthread

How to use an initialization list with std::thread as a member in C++11


I am trying to create a vector with a class as its template which has a std::thread member. However, I am not sure on how to properly create the initialization list using the thread. What I have currently is this:

class someclass 
{
public:
std::thread thread;
int id;

someclass(std::thread init_thread, int init_id) : 
    thread(&init_thread), 
    id(init_id)
{}
};

However, when I try to compile it in VS2012, I get the following error:

f:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(1152): error C2064: term does not evaluate to a function taking 0 arguments which point to the line: _VARIADIC_EXPAND_0X(_CLASS_BIND, , , , )

If I remove the & from the thread(&init_thread) initialization I get those errors instead: 1>f:\users...\project\source.cpp(43): error C2248: 'std::thread::thread' : cannot access private member declared in class 'std::thread' 1> f:\program files (x86)\microsoft visual studio 11.0\vc\include\thread(73) : see declaration of 'std::thread::thread' 1> f:\program files (x86)\microsoft visual studio 11.0\vc\include\thread(32) : see declaration of 'std::thread'

So, my question is: How would I correctly created such an initialization list?

Later on in the code I doing the following as well (just for reference...)

void function()
{
   // ....
   std::vector<someclass> v_someclass;
   v_someclass.push_back(someclass((std::thread(session, socket)),id));   
   // ....
}

Solution

  • There are two problems in your code. The most important one is that std::thread is not copy-constructable, but only move-copy constructable. You can make this intent clear by having an rvalue reference as parameter, and you have to use std::move when constructing the thread data member. Second, you should not take the address of the parameter. Your data member is not a pointer.

    someclass(std::thread&& init_thread, int init_id) : 
      thread(std::move(init_thread)), 
      id(init_id)
    

    This means you can only construct someclass using an std::thread rvalue. For example

    someclass sc0(std::thread(args), 42);
    std::thread t(args);
    someclass sc1(std::move(t), 42);
    

    Edit Note that you can actually have a value parameter: someclass(std::thread, int), but the error message you get when passing an lvalue is not as clear as the one you get with the rvalue reference parameter.