2016-07-13 8 views
0

Ich versuche, zwei Teile von Legacy-Code nachzurüsten. Einer der Teile implementiert ein Timeout für einen Funktionsaufruf. Bisher wurde es in C++ Methoden verwendet und funktioniert perfekt.Übergabe von C-Funktionen und -Parametern als rvalue-Referenzen

Jetzt ist es erforderlich, ein ähnliches Timeout für eine ältere C-Bibliothek zu implementieren. Ich versuche, den gleichen Code dafür zu verwenden, aber auf Probleme zu stoßen.

Hier ist eine vereinfachte Version des Codes, mit dem Problem, vor dem ich stehe.

uint32_t myFunc1() 
{ 
    return 0; 
} 

uint32_t myFunc2(uint32_t a) 
{ 
    return a; 
} 

int main() 
{ 
    uint32_t dummy = 1; 
    timedCall(myFunc1); //compiles fine. 
    timedCall(myFunc2, dummy); //compile errors C2672, C2893 
} 

template <class F, class... Args> 
uint32_t timedCall(F &&f, Args&&... a) 
{ 
    try 
    { 
     std::packaged_task<uint32_t(Args...)> myTask(std::bind(f, a...)); 
     auto res = myTask.get_future(); 
     std::thread(std::move(myTask), a...).detach(); //This is where the issue is.   

     //Do other stuff 
    } 
    catch(...) 
    { 
     //handle exceptions 
    } 

    return 0; //return something 
} 

ich folgende Fehler:

C2672 'std::invoke': no matching overloaded function found 
C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' 

Könnte mir bitte jemand sagen, was ich falsch mache und wie man es beheben? Ich verwende Visual Studio 2015.

+0

Können Sie das reduzieren Code bis zu dem Keast erforderlich, um den Fehler zu generieren? Welche genaue Version von MSVC verwenden Sie? Gibt es keine anderen Fehlermeldungen? Normalerweise gibt es Kontext. – Yakk

+0

Kompiliert mit Clang in C++ 11 oder C++ 14 Modus. –

+0

@Yakk, sorry, hätte genauer sein sollen. Ich verwende Visual Studio 2015. – Amol

Antwort

1

Problem ist mit std zu folgen :: Thread akzeptiert die packaged_task nicht, std::thread(f, a...) hat gut funktioniert. Jetzt würde ich nicht versuchen, in std::thread Gewässern Versand (edit: wo Andrei R. eine gute Erklärung im Detail zur Verfügung gestellt, was schief gelaufen ist), während std::async wird die Aufgabe viel einfacher für Sie machen:

template <class F, class... Args> 
uint32_t timedCall(F &&f, Args&&... a) 
{ 
    try 
    { 
     auto res = std::async 
     (
      std::launch::async, 
      std::forward<F>(f), 
      std::forward<Args>(a)... 
     ); 
     //Do other stuff 
    } 
    catch(...) 
    { 
     //handle exceptions 
    } 

    return 0; //return something 
} 
+0

Vielen Dank! Das hat sehr geholfen! – Amol

1

Wenn Sie std::bind(f, a...) verwenden, erhalten Sie Callable-Objekt, das mit obj() aufgerufen werden kann. Aber Konstruktor von std::packaged_task<uint32_t(Args...)> erwartet Objekt, das mit obj(a...) aufrufbar ist. Einige Compiler ignorieren jedoch möglicherweise zusätzliche Argumente.

Sie müssen entweder auf bind entfernen:

std::packaged_task<uint32_t(Args...)> myTask(f); 
auto res = myTask.get_future(); 
std::thread(std::move(myTask), std::forward<Args>(a)...).detach(); 

oder rufen Syntax ändern:

std::packaged_task<uint32_t()> myTask(std::bind(f, std::forward<Args>(a)...)); 
auto res = myTask.get_future(); 
std::thread(std::move(myTask)).detach(); 

oder (besser) Aconcagua Lösung

+1

Ich empfehle, auch std :: forward zur ersten Lösung hinzuzufügen. – Aconcagua

+0

Danke für die Erklärung. Es half mir zu verstehen, was in diesem Code passiert, den ich gerade geerbt hatte. – Amol

Verwandte Themen