2013-08-19 7 views
10

Betrachten Sie meinen Testcode:Fehler std :: Thread auf Mac OS X mit Klappern zu erstellen: "Versuch, eine gelöschte Funktion verwenden"

#include <thread> 

class Foo { 
public: 
    void threadFunc() {} 
    void startThread() { 
     _th = std::thread(&Foo::threadFunc, *this); 
    } 
private: 
    std::thread _th; 
}; 

int main(int argc, char *argv[]) 
{  
    Foo f; 
    f.startThread(); 
    return 0; 
} 

Dies ist ein Fehler, der es erzeugt:

../untitled/main.cpp:13:14: warning: unused parameter 'argc' [-Wunused-parameter] 
int main(int argc, char *argv[]) 
      ^
../untitled/main.cpp:13:26: warning: unused parameter 'argv' [-Wunused-parameter] 
int main(int argc, char *argv[]) 
         ^
In file included from ../untitled/main.cpp:1: 
In file included from /usr/bin/../lib/c++/v1/thread:90: 
In file included from /usr/bin/../lib/c++/v1/__functional_base:15: 
/usr/bin/../lib/c++/v1/type_traits:1372:12: error: call to implicitly-deleted copy constructor of 'typename decay<Foo &>::type' (aka 'Foo') 
    return _VSTD::forward<_Tp>(__t); 
      ^~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/bin/../lib/c++/v1/__config:273:15: note: expanded from macro '_VSTD' 
#define _VSTD std::_LIBCPP_NAMESPACE 
      ^
/usr/bin/../lib/c++/v1/thread:351:33: note: in instantiation of function template specialization 'std::__1::__decay_copy<Foo &>' requested here 
           __decay_copy(_VSTD::forward<_Args>(__args))...)); 
           ^
../untitled/main.cpp:7:15: note: in instantiation of function template specialization 'std::__1::thread::thread<void (Foo::*)(), Foo &, void>' requested here 
     _th = std::thread(&Foo::threadFunc, *this); 
      ^
../untitled/main.cpp:10:17: note: copy constructor of 'Foo' is implicitly deleted because field '_th' has an inaccessible copy constructor 
    std::thread _th; 
       ^

und wenn ich einen Thread wie folgt zu erstellen: _th = std::thread(&Foo::threadFunc, std::ref(*this));

ich:

../untitled/main.cpp:13:14: warning: unused parameter 'argc' [-Wunused-parameter] 
int main(int argc, char *argv[]) 
      ^
../untitled/main.cpp:13:26: warning: unused parameter 'argv' [-Wunused-parameter] 
int main(int argc, char *argv[]) 
         ^
In file included from ../untitled/main.cpp:1: 
/usr/bin/../lib/c++/v1/thread:330:5: error: attempt to use a deleted function 
    __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 
    ^
/usr/bin/../lib/c++/v1/thread:340:5: note: in instantiation of function template specialization 'std::__1::__threaad_execute<void (Foo::*)(), std::__1::reference_wrapper<Foo> , 1>' requested here 
    __threaad_execute(*__p, _Index()); 
    ^
/usr/bin/../lib/c++/v1/thread:352:41: note: in instantiation of function template specialization 'std::__1::__thread_proxy<std::__1::tuple<void (Foo::*)(), std::__1::reference_wrapper<Foo> > >' requested here 
    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); 
             ^
../untitled/main.cpp:7:15: note: in instantiation of function template specialization 'std::__1::thread::thread<void (Foo::*)(), std::__1::reference_wrapper<Foo> , void>' requested here 
     _th = std::thread(&Foo::threadFunc, std::ref(*this)); 
      ^
/usr/bin/../lib/c++/v1/type_traits:833:5: note: function has been explicitly marked deleted here 
    ~__nat() = delete; 
    ^

Was mache ich falsch? Ich habe solche Probleme unter Windows mit VS2012 nicht. Ich hatte dieses Problem auch nicht mit der Standard-stdlib-Implementierung auf dem Mac, aber jetzt muss ich libC++ verwenden.

Mein Compiler-Flags: -std=c++11 -mmacosx-version-min=10.7 -stdlib=libc++

+1

Die (standardkonforme) Version mit 'std :: ref' [funktioniert korrekt auf Coliru] (http://coliru.stacked-crooked.com/view ? id = 61d9f8137948ff6540e8c2235ff01bdd-e1204655eaff68246b392dc70c5a32c9), Sie sind wahrscheinlich über einen Fehler in Ihrem Compiler/stdlib gestolpert. – Casey

Antwort

11
_th = std::thread(&Foo::threadFunc, *this); 

Dieser versucht, eine Kopie von *this speichern im neuen Thread-Objekt zu machen, aber Ihre Art ist nicht kopierbar, weil sein Mitglied _th nicht kopierbar ist.

Sie wollen wahrscheinlich einen Zeiger auf das Objekt speichern, keine Kopie des Objekts:

_th = std::thread(&Foo::threadFunc, this); 

N. B. Ihr Programm wird beendet, weil Sie dem Thread nicht beitreten. In Ihrer Destruktor Art sollten Sie tun, so etwas wie:

~Foo() { if (_th.joinable()) _th.join(); } 
+0

Ich dachte "Thread" erwartet einen Verweis auf eine Klasse, kein Zeiger. Vielen Dank. –

+0

Nein, es wird ein beliebiger aufrufbarer Typ erwartet, und ein Memberfunktionszeiger wie '& Foo :: threadFunc' kann mit einem Argument vom Typ' Foo' oder 'Foo &' oder 'Foo *' aufgerufen werden. Sie können eine Referenz übergeben, wenn Sie möchten, aber das ist nicht, was Ihr Code tut. Wenn Sie eine Referenz übergeben möchten, verwenden Sie 'std :: thread (& Foo :: threadFunc, std :: ref (* this));', also versucht es nicht, eine Kopie zu erstellen. –

+1

Wie Sie in der Frage sehen können, habe ich auch 'std :: ref' versucht und es hat auch nicht funktioniert. –