2010-12-09 44 views
2

可能是另一個愚蠢的問題,這是我在壞的C++書籍中學習的結果(我打算糾正這個問題)。在模板函數中鍵入錯誤

我用sstream玩和嘗試了以下功能:

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

當我把它想:

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

它工作正常。但是,如果我把它想:

int i = fromString("123"); 

我得到了一個編譯錯誤:

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

我以爲,編譯器會明白,如果我指定的值到int話,我一定要談fromString<int>,但似乎並非如此。

我錯過了什麼嗎?我是否應該總是指定模板化函數的類型?或者當模板類型是返回類型?或者當模板類型不能由輸入類型決定時?

回答

9

不,編譯器無法單獨從返回類型推導出模板參數。你必須要具體,你最初是:

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

一個編譯器爲什麼不能在這種情況下,推斷是因爲許多類型的可轉換爲int的原因。例如:

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

在這種情況下,編譯器如何知道不要實例化fromString<Gizmo>()

+0

humm ...邪惡!我現在明白了。謝謝。猜測我太習慣於Haskell,它純粹是功能性的,所以這種自動轉換是不可能的。 – 2010-12-09 21:02:02

1

除了什麼約翰說這個是所謂的「非抵扣範圍內」,有時你可以避開這樣的事情通過提供模板類型的虛擬參數:

#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; 
} 

那幫助編譯器推斷出類型並避免你必須明確指定它。如上例所示,變量的名稱非常簡短,特別有用。

3

你可以用一個簡單的技巧得到這個效果。

#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; 
}