Как использовать список инициализации с std::thread в качестве члена в С++ 11

Я пытаюсь создать вектор с классом в качестве шаблона, который имеет член std::thread. Однако я не уверен, как правильно создать список инициализации с помощью потока. В настоящее время у меня есть это:

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

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

Однако, когда я пытаюсь скомпилировать его в VS2012, я получаю следующую ошибку:

f:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(1152): ошибка C2064: термин не оценивается как функция, принимающая 0 аргументов, которые указывают на строку: _VARIADIC_EXPAND_0X(_CLASS_BIND, , , , )

Если я удаляю & из инициализации потока (& init_thread), вместо этого я получаю следующие ошибки: 1>f:\users...\project\source.cpp(43): ошибка C2248: 'std::thread::thread': невозможно получить доступ к частному члену, объявленному в классе 'std::thread' 1> f:\program files (x86)\microsoft visual studio 11.0\vc\include\thread(73): см. объявление 'std::thread::thread' 1> f:\program files (x86)\microsoft visual studio 11.0\vc\include\thread(32): см. объявление 'std::thread'

Итак, мой вопрос: как правильно создать такой список инициализации?

Позже в коде я также делаю следующее (просто для справки...)

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

person Pita    schedule 12.04.2014    source источник


Ответы (1)


В вашем коде две проблемы. Самый важный из них заключается в том, что std::thread нельзя построить с помощью копирования, а можно только создать с помощью перемещения и копирования. Вы можете прояснить это намерение, указав ссылку rvalue в качестве параметра, и вы должны использовать std::move при создании члена данных потока. Во-вторых, вы не должны брать адрес параметра. Ваш элемент данных не является указателем.

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

Это означает, что вы можете создать someclass только с использованием std::thread rvalue. Например

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

Изменить Обратите внимание, что вы можете фактически иметь параметр значения: someclass(std::thread, int), но сообщение об ошибке, которое вы получаете при передаче lvalue, не такое ясное, как сообщение, которое вы получаете со ссылкой на rvalue параметр.

person juanchopanza    schedule 12.04.2014
comment
Вам не нужно sn rvalue ref в качестве параметра. Значение работает нормально. - person Yakk - Adam Nevraumont; 12.04.2014
comment
Спасибо за быстрый ответ! Этот ответ - именно то, что я искал, и нигде в сети не смог получить четкого понимания. - person Pita; 12.04.2014
comment
@juanchopanza Думаю, еще один дополнительный вопрос относительно конструкции. Если бы я хотел построить объект анонимно, используя его в push_back вектора, почему я не мог просто сделать это, как v_someclass.push_back(someclass((std::thread(session, socket)),id)); Разве это не то же самое, что определить их отдельно, как в someclass sc0(std::thread(session, socket),42); v_someclass.push_back(sc0);? - person Pita; 12.04.2014
comment
@Yakk Да, правильно. Но я предпочитаю сделать намерение более ясным, а также извлечь выгоду из более четкого сообщения об ошибке в случае передачи lvalue. Я добавил предложение об этом. - person juanchopanza; 12.04.2014