[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