[cfe-dev] thread(F&&) fails when F is not MoveAssignable
Gordon Henriksen
gordonhenriksen at me.com
Sun Dec 16 15:27:21 PST 2012
On 2012-12-16, at 14:55, Howard Hinnant wrote:
> On Dec 16, 2012, at 5:22 PM, Gordon Henriksen <gordonhenriksen at me.com> wrote:
>
>> [Sorry for the cross-post, but cfe-users doesn't seem to be active yet.]
>>
>> The snippet at the end of this message fails to compile with clang-libc++.
>>
>> Is LaunchByMove() invalid C++11, or is this a libc++ bug?
>>
>>
>> cat <<'EOT' >test.cpp
>> #include <thread>
>> class CopyableNotAssignable {
>> int &n_;
>> public:
>> CopyableNotAssignable(int &n) : n_(n) { }
>> };
>> void LaunchByMove() {
>> int n;
>> std::thread(CopyableNotAssignable(n)).join(); // expect-error
>> }
>> void LaunchByCopy() {
>> int n;
>> CopyableNotAssignable cna(n);
>> std::thread(cna).join(); // successful
>> }
>> EOT
>> xcrun clang -std=c++0x -stdlib=libc++ -c test.cpp
>
> CopyableNotAssignable does not appear to be a callable object with zero parameters. LaunchByMove and LaunchByCopy should both fail. Or technically, they exhibit undefined behavior, so anything could happen. A compile-time error is the highest quality solution.
>
> Howard
Thanks, Howard; that is an error in my reduction. The true test is this, and using 'bool *flag_;' instead of 'bool &flag_;' does make this case compile for reasons which are mysterious to me.
namespace {
class SimpleJoinThread {
bool &flag_;
public:
SimpleJoinThread(bool &flag) : flag_(flag) { }
void operator()() { flag_ = true; }
};
} // End anonymous namespace.
TEST(ThreadTests, SimpleJoin) {
bool flag = false;
std::thread(SimpleJoinThread(flag)).join();
EXPECT_TRUE(flag);
}
There's something more complex going on in the compilation unit, though; the reduced case I presented does compile on its own with the addition of void operator()() {}.
Sorry for the noise.
— Gordon
More information about the cfe-dev
mailing list