Bulletmagnet
Bulletmagnet

Reputation: 6042

Passing a member function to std::thread without address-of

I have the following code, which compiles happily with GCC 4.8.4, GCC 5.2.0 and clang 3.8.0 trunk (with -std=c++11)

#include <utility>
#include <thread>

struct Callable {
    static void run() {}
};

void start(Callable && c)
{
    std::thread t(&c.run); // construct thread
}

int main()
{
    Callable c;
    start(std::move(c));
}

(using std::move on an lvalue is not kosher but that's not the point).

However, if I change the thread constructor call to

std::thread t(c.run);

clang still compiles it but GCC 5.2.0 complains:

/home/bulletmagnet/workspace/zarquon/prog/msyncd/src/new_thread_test.cc: In function ‘void start(Callable&&)’:
/home/bulletmagnet/workspace/zarquon/prog/msyncd/src/new_thread_test.cc:10:24: error: no matching function for call to ‘std::thread::thread(void())’
     std::thread t(c.run);
                        ^
In file included from /home/bulletmagnet/workspace/zarquon/prog/msyncd/src/new_thread_test.cc:2:0:
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/include/c++/thread:133:7: note: candidate: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void(); _Args = {}]
       thread(_Callable&& __f, _Args&&... __args)
       ^
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/include/c++/thread:133:7: note:   no known conversion for argument 1 from ‘void()’ to ‘void (&&)()’
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/include/c++/thread:128:5: note: candidate: std::thread::thread(std::thread&&)
     thread(thread&& __t) noexcept
     ^
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/include/c++/thread:128:5: note:   no known conversion for argument 1 from ‘void()’ to ‘std::thread&&’
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/include/c++/thread:122:5: note: candidate: std::thread::thread()
     thread() noexcept = default;
     ^
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/include/c++/thread:122:5: note:   candidate expects 0 arguments, 1 provided

(GCC 4.8.4 also complains).

So, which compiler is right?

Upvotes: 0

Views: 266

Answers (1)

Jonathan Wakely
Jonathan Wakely

Reputation: 171403

I think Clang is right, EDG also accepts the code, so I've opened https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68386

The obvious workaround is to not use that weird syntax to refer to a static member function, but instead refer to it as Callable::run which will work with or without the & operator.

Upvotes: 1

Related Questions