Search

std::thread does not accept std::move by James K Edwards

Closed
as Fixed Help for as Fixed

2
0
Sign in
to vote
Type: Bug
ID: 737812
Opened: 4/19/2012 8:58:36 PM
Access Restriction: Public
Moderator Decision: Sent to Engineering Team for consideration
1
Workaround(s)
0
User(s) can reproduce this bug
This line fails to compile.

    std::thread th(&ThFun, std::move(prms));

std::bind requires copyable, but std::thread does not.
Details (expand)

Visual Studio/Team Foundation Server/.NET Framework Tooling version

Visual Studio 11 Beta

Steps to reproduce

copy and paste this and compile.

#include <thread>
#include <cassert>
#include <iostream>
#include <string>
#include <future>
#include <utility>

void ThFun(std::promise<std::string>& prms)
{
    std::string hello = "Hello From Future!\n";
    prms.set_value(hello);
}

int main()
{
    std::promise<std::string> prms;
    auto ftr = prms.get_future();
    std::thread th(&ThFun, std::move(prms));
    std::cout << "Hello from Main\n";
    std::string str = ftr.get();
    std::cout << str << std::endl;
    th.join();

    return 0;
}

Product Language

English

Operating System

Windows 8

Operating System Language

English

Actual results

1>------ Build started: Project: PromisesAndFutures, Configuration: Debug Win32 ------
1>Build started 4/20/2012 9:27:43 AM.
1>InitializeBuildStatus:
1> Creating "Debug\PromisesAndFutures.unsuccessfulbuild" because "AlwaysCreate" was specified.
1>ClCompile:
1> Main.cpp
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\tuple(119): error C2248: 'std::promise<_Ty>::promise' : cannot access private member declared in class 'std::promise<_Ty>'
1>         with
1>         [
1>             _Ty=std::string
1>         ]
1>         c:\program files (x86)\microsoft visual studio 11.0\vc\include\future(1575) : see declaration of 'std::promise<_Ty>::promise'
1>         with
1>         [
1>             _Ty=std::string
1>         ]
1>         c:\program files (x86)\microsoft visual studio 11.0\vc\include\tuple(486) : see reference to function template instantiation 'std::_Tuple_val<_Ty>::_Tuple_val<const _Ty&>(_Other)' being compiled
1>         with
1>         [
1>             _Ty=std::promise<std::string>,
1>             _Other=const std::promise<std::string> &
1>         ]
1>         c:\program files (x86)\microsoft visual studio 11.0\vc\include\tuple(486) : while compiling class template member function 'std::tuple<<unnamed-symbol>>::tuple(const std::tuple<<unnamed-symbol>> &)'
1>         with
1>         [
1>             <unnamed-symbol>=std::promise<std::string>
1>         ]
1>         c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(1140) : see reference to class template instantiation 'std::tuple<<unnamed-symbol>>' being compiled
1>         with
1>         [
1>             <unnamed-symbol>=std::promise<std::string>
1>         ]
1>         c:\program files (x86)\microsoft visual studio 11.0\vc\include\thread(50) : see reference to class template instantiation 'std::_Bind<_Forced,_Ret,_Fun,_V0_t,_V1_t,_V2_t,_V3_t,_V4_t,_V5_t,<unnamed-symbol>>' being compiled
1>         with
1>         [
1>             _Forced=true,
1>             _Ret=void,
1>             _Fun=void (__cdecl *const )(std::promise<std::string> &),
1>             _V0_t=std::promise<std::string>,
1>             _V1_t=std::_Nil,
1>             _V2_t=std::_Nil,
1>             _V3_t=std::_Nil,
1>             _V4_t=std::_Nil,
1>             _V5_t=std::_Nil,
1>             <unnamed-symbol>=std::_Nil
1>         ]
1>         c:\users\jim\documents\visual studio 11\projects\promisesandfutures\promisesandfutures\main.cpp(18) : see reference to function template instantiation 'std::thread::thread<void(__cdecl *)(std::promise<_Ty> &),std::promise<_Ty>>(_Fn,_V0_t &&)' being compiled
1>         with
1>         [
1>             _Ty=std::string,
1>             _Fn=void (__cdecl *)(std::promise<std::string> &),
1>             _V0_t=std::promise<std::string>
1>         ]
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:01.69
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Expected results

1 succeeded, 0 failed, 0 up-to-date, 0 skipped
File Attachments
0 attachments
Sign in to post a comment.
Posted by Microsoft on 5/7/2012 at 6:34 PM
Hi,

Thanks for reporting this bug. I've resolved it as Fixed because this compiles with my current build of VC11 (and you'll observe this in VC11 RTM).

However, this area is fragile, and we didn't intentionally fix this. The Connect bug http://connect.microsoft.com/VisualStudio/feedback/details/729886/std-thread-constructor-doesnt-handle-movable-object (internally DevDiv#377755) tracks the ultimate problem here: we used std::bind() to implement std::thread, but the Standard actually forbids that because they have different semantics. In particular, bound arguments are supposed to be presented as lvalues to bind() functors (so they can be invoked repeatedly), but as rvalues to thread functors.

Your code compiles because you're moving prms into the thread, and then having ThFun() take an lvalue reference. Very similar code, taking the promise by value or by rvalue reference, will not compile with VC11 (but should, according to C++11).

In the future, we will attempt to fix this, by reimplementing std::thread so it doesn't use std::bind(). However, we won't have enough time to do this for VC11 RTM.

If you have any further questions, feel free to E-mail me at stl@microsoft.com .

Stephan T. Lavavej
Visual C++ Libraries Developer
Posted by MS-Moderator10 [Feedback Moderator] on 4/20/2012 at 2:11 AM
Thanks for your feedback.

We are rerouting this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.
Posted by MS-Moderator01 on 4/19/2012 at 9:54 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
Posted by James K Edwards on 4/19/2012 at 8:59 PM
You can use std::ref, but it's not the same.