2012-06-19 6 views
12

diese Template-Funktion vor:ableiten Template-Argument von std :: Funktionsaufruf Signatur

template<typename ReturnT> 
ReturnT foo(const std::function<ReturnT()>& fun) 
{ 
    return fun(); 
} 

Warum ist es nicht möglich, dass der Compiler ReturnT aus dem übergebenen Anruf Signatur abzuleiten?

bool bar() { /* ... */ } 

foo<bool>(bar); // works 
foo(bar); // error: no matching function call 
+1

Eine Antwort auf [eine meiner vorherigen Fragen] (http://stackoverflow.com/questions/9625526/check-at-compile-time-if-template-argument-is-void) ermöglicht diese Art von Syntax. Ich hoffe das hilft. Es ist spezialisiert, wenn der Rückgabetyp auch ungültig ist. – chris

+0

@chris Danke für den Hinweis - ich werde versuchen, es zu verstehen :) –

+0

N.B. sehr ähnlich zu http://Stackoverflow.com/q/7608741/981959 und http://Stackoverflow.com/q/9242234/981959, aber ich denke, dass die Antworten hier für diese spezifische Frage klarer sind. –

Antwort

7
std::function<bool()> bar; 

foo(bar); // works just fine 

C++ kann nicht den Rückgabetyp aus Ihrer Funktion bar ableiten, weil es die Art müßte wissen, bevor es alle Konstrukteure finden kann, die Ihre Funktionszeiger nehmen.

Zum Beispiel, wer ist zu sagen, dass std::function<std::string()> hat keinen Konstruktor unter bool (*)()?

0

Die Funktion bar ist vom Typ bool (*)() oder so, dass: a normalen prä-C++ 11 Funktionstyp. Ich bin nicht so zuversichtlich in C++ 11, aber ich denke, der Compiler sieht nicht die Verbindung zwischen bool (*)() und const std::function<ReturnT()>&, auch wenn die erste implizit in die zweite konvertiert werden kann für ReturnT = bool.

+0

Wie kann ein Funktionszeiger in einen Funktionstyp umgewandelt werden? –

+0

Tatsächlich ist die Definition von std :: function egal, wie die Konvertierung fortschreitet: 'template Klassenfunktion ' wobei 'R' dafür bekannt ist,' bool' ... daher 'zu sein ReturnT' sollte für 'foo' nachvollziehbar sein, oder? –

+0

@Karl, aber 'std :: function' hat einen Konstruktor, der _any_ type nimmt, also kann' bool (*)() 'auch in' std :: function 'oder andere Typen konvertiert werden - es gibt kein einziges, Eine einzigartige Konvertierungssequenz, die nur eine einzige 'std :: function' Spezialisierung bedeutet, kann abgeleitet werden –

13

Ein Funktionszeiger vom Typ bool (*)() kann in std::function<bool()> konvertiert werden, ist aber nicht vom selben Typ, daher ist eine Konvertierung erforderlich. Bevor der Compiler prüfen kann, ob diese Konvertierung möglich ist, muss er ReturnT als bool ableiten, aber dazu muss er bereits wissen, dass std::function<bool()> eine mögliche Konvertierung ist, die nicht möglich ist, bis es ReturnT ... ergibt ... sehen Sie das Problem?

Bedenken Sie auch, dass bool(*)() auch in std::function<void()> oder std::function<int()> konvertiert werden könnte ... was sollte abgeleitet werden?

diese Vereinfachung vor:

template<typename T> 
    struct function 
    { 
    template<typename U> 
     function(U) { } 
    }; 

template<typename T> 
    void foo(function<T>) 
    { } 

int main() 
{ 
    foo(1); 
} 

Wie kann der Compiler wissen, ob Sie function<int> oder function<char> oder function<void> schaffen wollte, wenn sie alle int eine Form aufgebaut werden kann?