Почему передача аргументов ссылки на объект в функцию потока не компилируется?

Я столкнулся с проблемой, используя новый интерфейс std::thread c++11.
Я не могу понять, как передать ссылку на std::ostream в функцию, которую будет выполнять поток.

Вот пример с передачей целого числа (компилируется и работает, как и ожидалось в gcc 4.6):

void foo(int &i) {
    /** do something with i **/
    std::cout << i << std::endl;
}

int k = 10;
std::thread t(foo, k);

Но когда я пытаюсь передать ostream, он не компилируется:

void foo(std::ostream &os) {
    /** do something with os **/
    os << "This should be printed to os" << std::endl;
}

std::thread t(foo, std::cout);

Есть ли способ сделать именно это, или это вообще невозможно??

NB: из-за ошибки компиляции кажется, что это удаленный конструктор...


person Benjamin A.    schedule 28.11.2011    source источник
comment
Для примитивов: stackoverflow .com/questions/5116756/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 17.06.2015


Ответы (1)


Потоки копируют свои аргументы (подумайте об этом, это правильно). Если вам нужна явная ссылка, вы должны обернуть ее std::ref (или std::cref для постоянных ссылок):

std::thread t(foo, std::ref(std::cout));

(Оболочка ссылки — это оболочка с семантикой значений вокруг ссылки. То есть вы можете скопировать оболочку, и все копии будут содержать одну и ту же ссылку.)

Как обычно, этот код корректен только до тех пор, пока объект, на который вы ссылаетесь, остается живым. Пусть покупатель будет бдителен.

person Kerrek SB    schedule 28.11.2011
comment
@JohnDibling: Если вы мазохист и считаете, что в вашем C слишком много plusplus, то да. - person Kerrek SB; 28.11.2011
comment
Наверное, у меня есть мазохистские наклонности. - person John Dibling; 28.11.2011
comment
@JohnDibling: Нет. Передача указателя не дает вам ссылку. - person Lightness Races in Orbit; 28.11.2011
comment
@Tomalak: Я также не говорил и не подразумевал, что это так. - person John Dibling; 28.11.2011
comment
Передача указателя потребует изменения логики программы, я думаю, мы все можем с этим согласиться. - person Kerrek SB; 28.11.2011
comment
Для справки, я не рекомендую передавать по указателю в общем случае. Единственная причина, по которой я упомянул об этом в комментарии, была для полноты. Не то чтобы это имело большое значение, но я проголосовал, прежде чем прокомментировать. - person John Dibling; 28.11.2011
comment
Ах, спасибо, я забыл о передаче аргумента потока по значению. А что насчет дела int? - person Benjamin A.; 29.11.2011
comment
@BenjaminA.: А как насчет этого? Он также передается по значению. - person Kerrek SB; 29.11.2011