Przeczytałem przez std::thread documentation at cppreference (nie zawsze w 100% dokładny, wiem) i zauważyłem następującą definicję zachowania std::thread
po podaniu "wskaźnika do danych-członka" (nie „wskaźnik do członków funkcji”) jako pierwszego argumentu (f
) i obiektem wymaganej klasy jako drugi argument (t1
po skopiowaniu nitki-lokalny przechowywania):std :: wątek ze wskaźnikiem do elementu danych
jeśli N == 1 i f jest wskaźnikiem do obiektu danych elementu klasy, to jest on dostępny. Wartość obiektu jest ignorowana. W efekcie wykonywany jest następujący kod: t1. * F if, a typ t1 to T, odniesienie do T lub odniesienie do typu otrzymanego z T. (* t1). * F w przeciwnym wypadku.
Teraz nie planuję używać w ten sposób std::thread
, ale jestem oszołomiony tą definicją. Wydaje się, że jedyną rzeczą, która się dzieje jest to, że członek danych jest dostępny, a wartość zignorowana, co nie wydaje się, że może mieć jakiekolwiek obserwowalne efekty uboczne, co oznacza (o ile mogę powiedzieć), że równie dobrze może być no-op. (Może brakuje mi czegoś oczywistego ...?)
Początkowo myślałem, że to może być błąd drukarski, który oznaczał, że członek danych jest dostępny, a następnie wywoływany (ponieważ może to być obiekt do wywołania, nawet jeśli to nie jest funkcja), ale ja testowałem to z następującego kodu w gcc-4.7 i rzeczywiście nie ma połączenia:
#include <iostream>
#include <thread>
struct S
{
void f() {
std::cout << "Calling f()" << std::endl;
}
struct {
void operator()() {
std::cout << "Calling g()" << std::endl;
}
} g;
};
int main(int, char**)
{
S s;
s.f(); // prints "Calling f()"
s.g(); // prints "Calling g()"
std::cout << "----" << std::endl;
auto x = &S::f; // ptr-to-mem-func
auto y = &S::g; // ptr-to-data-mem
(s.*x)(); // prints "Calling f()"
(s.*y)(); // prints "Calling g()"
std::cout << "----" << std::endl;
std::thread t(x, &s);
t.join();
// "Calling f()" printed by now
std::thread u(y, &s);
u.join();
// "Calling g()" not printed
return 0;
}
Czy istnieje jakiś cel do tej definicji, która nie wydaje się niczego osiągnąć? Dlaczego zamiast tego sprawić, by przekazanie "wskaźnika do elementu danych do pobrania" działało jak funkcja "wskazywania na członka" i sprawić, że przekazanie "braku wskaźnika do danych-członka nieopublikowanego" było błędem? W rzeczywistości wydaje się, że byłby to najłatwiejszy sposób implementacji, ponieważ wywoływanie "wskaźnika do danych-elementu-wywoływalnego" ma równoważną składnię do wywoływania jako "wskaźnik-do-funkcji-członka" w innych kontekstach (chyba że jest coś w różnorodności szablonowej specjalizacji i reguł SFINAE, co sprawia, że trudno jest je traktować równoważnie ...?)
To nie jest coś, czego potrzebuję do rzeczywistego kodu, ale fakt, że ta definicja istnieje, pozwala mi podejrzewać, że Brakuje mi czegoś fundamentalnego, co mnie martwi ... czy ktoś może mnie o tym poinformować?
+1 To sformułowanie pochodzi od definicji "INVOKE", która jest podana w 20.8.2 normy. Jest pytanie z takim samym zamiarem, jak twoje, szczególnie odnośnie tego sformułowania w definicji "INVOKE": http://stackoverflow.com/questions/12638393/why-does-invoke-facility-in-the-c11-standard-refer -to-danych-członków – jogojapan