2010-12-09 2 views
2

Wahrscheinlich eine andere dumme Frage, die aus meinem Studium in schlechten C++ Buch resultiert (ich beabsichtige, dies zu korrigieren).Typ Fehler in einer Vorlage-Funktion

Ich war mit sstream spielen und versucht, die folgende Funktion:

template <class num> num fromString(const std::string& str) { 
    std::istringstream ss(str); 
    num temp; 
    ss >> temp; 
    return temp; 
} 

Als ich es nennen mag:

int i = fromString<int>("123"); 

es ok funktioniert. Aber wenn ich es nennen mag:

int i = fromString("123"); 

ich einen Übersetzungsfehler bekam:

error: no matching function for call to ‘fromString(std::string&)’ 

dachte ich, der Compiler würde verstehen, dass, wenn ich den Wert auf eine int Zuweisung dann muss ich reden fromString<int>, aber es scheint, dass es nicht der Fall ist.

Fehle ich etwas? Soll ich immer den Typ einer Vorlagenfunktion angeben? Oder nur, wenn der Vorlagentyp der Rückgabetyp ist? Oder nur, wenn der Schablonentyp nicht durch die Arten der Eingaben bestimmt werden kann?

Antwort

9

Nein, der Compiler kann Vorlagenparameter nicht allein vom Rückgabetyp ableiten. Sie müssen spezifisch sein, wie Sie ursprünglich waren:

int i = fromString<int>("123"); 

Einer der Gründe, warum der Compiler in diesem Fall nicht ableiten kann, ist, weil eine Reihe von Typen konvertierbar int sein könnte. Zum Beispiel:

class Gizmo 
{ 
public: 
    operator int() const; 
}; 

Wie würde der Compiler weiß nicht, fromString<Gizmo>() in diesem Fall instanziiert?

+0

humm ... Wicked! Ich hab es jetzt. Vielen Dank. Schätze, ich bin zu sehr an Haskell gewöhnt, was rein funktional ist und daher ist diese Art der automatischen Konvertierung nicht möglich. –

+0

Heh, verwöhnt von C++. Das habe ich noch nie gehört. :) –

1

Zusätzlich zu dem, was sagte John darüber zu sein, was ein ‚Nicht-ableitbar Kontext‘ genannt wird, kann man manchmal um Dinge wie diese erhalten, indem ein Dummy-Parameter des Vorlagentyp bereitstellt:

#include <sstream> 
#include <string> 

template <typename T> 
T from_string(const std::string& s, const T& /*dummy*/) 
{ 
    std::stringstream ss; 
    ss << s; 
    T t; 
    ss >> t; 
    return t; 
} 

int main() 
{ 
    std::string s = "23"; 
    int i = from_string(s, i); 
    return 0; 
} 

That hilft dem Compiler, den Typ abzuleiten und vermeidet, dass Sie ihn explizit angeben müssen. Es ist besonders nützlich, wenn der Name der Variablen wie im obigen Beispiel schön und kurz ist.

3

Sie können diesen Effekt mit einem einfachen Trick erhalten.

#include <sstream> 
#include <string> 
using namespace std; 

struct from_string { 
    string str; 
    from_string(const string& s) : str(s) { } 
    template <typename T> 
    operator T() const { 
     T ret; 
     stringstream ss(str); 
     ss >> ret; 
     return ret; 
    } 
} 

int main() { 
    string s("1234"); 
    int a = from_string(s); 
    return 0; 
}