问题
In writing test code for this question I found that the commented line below does not compile on GCC 4.7.2:
#include <thread>
#include <iostream>
struct S {
void f() {
std::cout << "Calling f()" << std::endl;
}
};
int main()
{
S s;
// std::thread t(&S::f, s); // does not compile?
std::thread t(&S::f, &s);
t.join();
}
But cppreference seems to claim that the "this" argument can be passed equivalently as an object, reference to object, or pointer to object:
If f is pointer to a member function of class T, then it is called. The return value is ignored. Effectively, the following code is executed: (t1.*f)(t2, ..., tN) if the type of t1 is either T, reference to T or reference to type derived from T. ((*t1).*f)(t2, ..., tN) otherwise.
I actually think this sounds terrible, and would prefer std::thread
only allow either pointer or reference semantics instead of accepting them interchangeably, but given that it seems like it's supposed to, is the above a GCC/libstdc++ bug (or am I misinterpreting cppreference)?
回答1:
Seems like tonight it's GCC Bug Party :-)
Jokes aside, this is most certainly a bug. My answer to the linked question actually contains the proof, but since it is not emphasized, I will repeat it here.
This is how the INVOKE
facility, in terms of which the behavior of std::thread
's constructor (see the linked answer) is defined in the C++11 Standard
Define INVOKE (f, t1, t2, ..., tN) as follows:
— (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;
— ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous item;
— t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;
— (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types described in the previous item;
— f(t1, t2, ..., tN) in all other cases.
The sentence in bold font effectively specifies that the line:
std::thread t(&S::f, s);
Should compile. Therefore, this qualifies as a bug.
Besides, that does line compile on GCC 4.8.0 (beta) and Clang 3.2.
来源:https://stackoverflow.com/questions/15080200/gcc-4-7-2-stdthread-with-pointer-to-member-function