Re: Passing std::unique_ptr to std::thread's target
Am 10.08.2011 22:14, schrieb Andy Venikov:
Sorry if this topic has been already covered - I've been out for awhile
and haven't been following. Quick search didn't produce anything.
#include <thread>
#include <memory>
Formally you are missing to include <utility>, because you refer to
std::move.
void threadMain(std::unique_ptr<int> inPtr)
{
....
}
int main(int, char**)
{
std::unique_ptr<int> outPtr(new int(42));
std::thread thr(threadMain, std::move(outPtr)); //Error here.
}
This does not compile under gcc 4.5 and 4.6
Is it gcc's problem or is it really the correct behavior?
I expect the code to be well-formed if fixed as shown above. Have you
tried gcc 4.7? What is the precise error message?
I'm not good at reading standardeese, but this:
[30.3.1.2(4)]
"Effects: Constructs an object of type thread. The new thread of
execution executes INVOKE (DECAY_-
COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)
with the calls to
DECAY_COPY being evaluated in the constructing thread."
seems to imply that it should be possible.
Yes.
Passing a unique_ptr (any move-only object for that matter) to a
thread seems like a very useful thing to be
prohibited by the standard.
And for that reason the specification was formed this way.
So, if I'm correct at assuming that it's a gcc's problem, what are my
options (Short of switching to a shared_ptr)?
Without further back-ground information available I expect the code to
compile successfully.
I have a guess, though: I assume that gcc does use std::bind internally
to implement the thread constructor. There exists currently a wording
problem described in LWG issue
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2021
for std::bind (and some other functions). The most recent proposed
resolution (not visible in the link above) suggests to change
[func.bind.bind] p3 as follows:
"Returns: A forwarding call wrapper g with a weak result type (20.8.2).
The effect of g(u1, u2, ..., uM) shall be INVOKE(fd,
<ins>std::forward<V1>(</ins>v1<ins>)</ins>,
<ins>std::forward<V2>(</ins>v2<ins>)</ins>, ...,
<ins>std::forward<VN>(</ins>vN<ins>)</ins>, result_of<FD cv <ins>&</ins>
(V1, V2, ..., VN)>::type), where cv represents the cv-qualifiers of g
and the values and types of the bound arguments v1, v2, ..., vN are
determined as specified below. [...]"
While LWG issue 2021 points to a defect in the wording of std::bind, the
intention clearly seems to be to provide lvalues of the "decayed"
functor and of the "decayed" functor arguments to the conceptual INVOKE
function, so with or without the wording changes the problem will
probably remain for std::bind. This has the effect that if you replace
the line
std::thread thr(threadMain, std::move(outPtr));
by
std::bind(threadMain, std::move(outPtr))();
the code should be ill-formed. I find this decision a bit unfortunate
but I have been told that it must be necessary, because of
backward-compatibility reasons in regard to std::bind. I suggest to open
a new discussion in regard to std::bind if you disagree with that
position as well.
HTH & Greetings from Bremen,
- Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]