Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why std::thread accepts a functor by forwarding reference

Why does a std::thread object accept the function parameter by forwarding reference and then make a copy of the object with decay_copy? Wouldn't it be easier to just accept the function object by value?

In general why would one not template a function so as to take a function object by value? Can reference-ness not be imitated with reference_wrappers (which would be more explicit, and also conveniently has a member operator() to call the stored function)?

like image 413
Curious Avatar asked Jul 23 '16 22:07

Curious


1 Answers

Why does a std::thread object accept the function parameter by forwarding reference and then make a copy of the object with decay_copy? Wouldn't it be easier to just accept the function object by value?

It has to have a copy of the function object in a storage that it can guarantee lasts as long as the thread it is about to launch lasts.

A function argument to construct std::thread would not last that long, as the line where std::thread is created can end long before the created thread ends.

So it must make a copy. If it took its argument by-value, it would make a copy when the constructor was called, then have to make another copy to the persistent storage. By taking it by forwarding reference, it makes exactly one copy.

Now this additional copy could be moved-to, making the extra overhead one extra move. This is still extra overhead, as not all constructs are cheap to move.

In general why would one not template a function so as to take a function object by value?

Because that mandates an extra move.

Can reference-ness not be imitated with reference_wrappers (which would be more explicit, and also conveniently has a member operator() to call the stored function)?

In the case where you intend to store the function object, taking by forwarding reference saves a move, and doesn't require much extra work on the part of the writer of the function-object taking code.

If the caller passed in a reference wrapper, the value stored would be the reference wrapper, which has a different meaning.

like image 80
Yakk - Adam Nevraumont Avatar answered Nov 10 '22 23:11

Yakk - Adam Nevraumont