2012-05-14 67 views
2

我想寫一個簡單的函數,將從一個範圍內的用戶輸入給我一個數字。爲什麼模板試圖用'int'而不是'int'實例化?

當instanciating這個功能我明確告訴它我想它實例化與int但我仍然得到錯誤:

thermo.cpp:105:31: error: no matching function for call to ‘getInput(int&)’ 

爲什麼試圖尋找一個函數,它int&作爲參數?

template<class T, T min = std::numeric_limits<T>::min, T max = std::numeric_limits<T>::max> 
T getInput(T default_value = T()){ 
    std::string input; 
    T myNumber = T(); //default inits 
    while(true){ 
    getline(cin, input); 

    if(input.length() == 0){ 
     return default_value; 
    } 

    // This code converts from string to number safely. 
    stringstream myStream(input); 
    if (myStream >> myNumber){ 
     if(myNumber > max || myNumber < min){ 
     stringstream ss; 
     ss << "Input out of bounds. Received " << myNumber << " expected between " << min << " and " << max << "."; 
     throw invalid_argument(ss.str()); 
     } 
     return myNumber; 
    } 

    cout << "Invalid number, please try again" << endl; 
    } 
} 

void get(const std::string& prompt, int& param){ 
    cout << prompt << " [" << param << "]:"; 
    param = getInput<int,0>(param); // i specifically tell it i want 'int', why am i getting 'int&'? 
} 

更新

如果我嘗試CharlesB建議:

void get(const std::string& prompt, int& param){ 
    cout << prompt << " [" << param << "]:"; 
    param = getInput<int,0>(int(param)); 
} 

我得到

thermo.cpp:105:36: error: no matching function for call to ‘getInput(int)’

忘記:

g++ 4.5.3 under cygwin

命令行:

$ g++ thermo.cpp -o thermo.exe -Wall -pedantic -std=c++0x

更新2

如果我這樣稱呼它

void get(const std::string& prompt, int& param){ 
    cout << prompt << " [" << param << "]:"; 
    param = getInput<int,0,15>(int(param)); // fully parameterized 
} 

它的作品...但我寧願不指定上限(每次通話時甚至不需要numeric_limits)。

回答

3

不要使用模板minmax

template<class T> 
T getInput(T default_value = T(), T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max()); 

沒有理由使用模板這些參數(除了一個事實,即它不工作)。

編輯:不能使用這些參數作爲模板值,因爲std::numeric_limits<T>::min()是一個函數,它的值是在運行時已知的,模板值參數都被綁定在編譯時的值。這是有效的:

template<class T, T min = 0, T max = 5> 
T getInput(T default_value); 

由於0和5在編譯期間已知。

+0

是的,那也來到我身邊。但接下來的另一個問題是:爲什麼'min'和'max'制動功能的查找... – RedX

+0

你去了哪裏,編輯了我的答案。 – mfontanini

+0

是的,就是這樣...誰決定做這些功能,而不是常量... – RedX

1

模板函數使用參數類型實例化,paramint&

而是做

param = getInput(int(param)); 

而且MIN和MAX不能模板參數,模板參數是類,類型名或POD。

+0

如果我這樣做,我得到:'thermo.cpp:105:36:錯誤:沒有匹配的福調用'getInput(int)''調用。這是莫名其妙... – RedX

+0

抱歉,嘗試編輯 – CharlesB

+0

也min和max不能是模板參數,模板參數是類或類型名稱,而不是值。 – CharlesB

2

我不知道這是否是問題,但我無法想象它是否有所幫助。這條線:

template<class T, T min = std::numeric_limits<T>::min, T max = std::numeric_limits<T>::max> 

...使用最小/最大作爲值,when they're really functions。也許這是混淆模板參數?

+0

不,這不是問題。我的意思是,這是一個問題,但這樣做並不能奏效。 – mfontanini

+1

@fontanini:這樣做確實可以使它與合理的符合C++ 11的編譯器一起工作,但如果OP停留在他的g ++版本中,這將無濟於事。 –

+0

@MikeSeymour不錯,不知道在C++ 11中這些函數變成了constexpr。 – mfontanini

2

錯誤代碼並不意味着你的想法。錯誤代碼是的縮寫:

沒有匹配的函數調用來getInput接受一個int修改的左值表達式作爲單個參數

int修改的左值表達是表達式的類型,你在這種情況下使用呼叫param。現在問題是這種格式的錯誤代碼的輸出是非常冗長的,並且使用非平凡類型的兩個或三個參數很難讀取,因此編譯器會彙總錯誤報告並告訴您:

沒有匹配的函數調用getInput(int&),請注意,這裏int&不是將被調用的函數的類型,因爲編譯器無法找到這樣的函數,而是它正在存在的參數的類型用於通話。

如果您執行CharlesB建議的更改,那麼您將收到一條不同的錯誤消息,指出它找不到getInput(int)。這裏的區別是int(param)創建了一個臨時(右值表達式),所以現在的錯誤反映了它。如果你有一個getInput(int&)函數,在第二種情況下,不能使用該過載,所以需要一個不同的錯誤代碼。

關於你得到那個錯誤代碼的原因,基本問題是std::numeric_limits<T>::max不是T類型。您的問題是SFINAE的基礎:您已經定義了一個模板,其中第二個和第三個參數爲TT應該使用std::numeric_limits<T>::min(和max)進行初始化。現在,當編譯器嘗試確定要調用的函數時,它會找到該模板,使用T代替int(您提供了確切類型),0代替min,然後嘗試推斷最後一個參數。此時,它將嘗試通過替換std::numeric_limits<T>::max中的已知模板參數,通過默認模板參數獲取T值(最後一個模板參數)。問題是std::numeric_limits<int>::max不是int,而是一個靜態成員函數,因此這些類型不匹配,從而導致替換失敗。該語言確定替換失敗不是錯誤SFINAE)並且它只意味着該模板將從函數調用的候選列表中刪除。因爲沒有其他匹配的重載,編譯器放棄並告訴你它找不到匹配的調用函數。

在C++ 11可以使用std::numeric_limits<T>::max(),作爲函數被標記爲const_expr並且因此可以是稱爲獲得T類型可以用來作爲模板參數的恆定表達,但如果是使用C++ 03編譯器時,您需要以不同的方式解決問題,例如將minmax移動到函數的默認參數,或者提供不同的重載,以便從用戶獲取值或調用函數(默認爲std::numeric_limist<T>::max如果參數不存在,但後者選擇是更繁瑣

相關問題