2017-01-30 56 views
1

我目前正試圖實現我自己的標準輸入讀取器供個人使用。我創建了一個從標準輸入中讀取整數的方法,並對其有效性進行了一些檢查。我的想法是,我從標準輸入讀取一個字符串,做幾次檢查,轉換爲int,做最後的檢查,返回已讀取的值。如果發生任何錯誤,我將只填寫errorHint以在std::cerr上打印並返回std::numeric_limits<int>::min()C++ std :: string到數字模板

我認爲這個想法非常簡單直接的實現,現在我想概括概念並製作方法模板,所以基本上我可以在編譯時選擇,無論何時我需要從標準輸入讀取哪種類型的我想要的整數(它可能是int,long,long long,unsigned long等等,但是是一個整數)。爲了做到這一點我已經創建了下面的靜態模板方法:

template< 
    class T, 
    class = typename std::enable_if<std::is_integral<T>::value, T>::type 
> 
static T getIntegerTest(std::string& strErrorHint, 
         T nMinimumValue = std::numeric_limits<T>::min(), 
         T nMaximumValue = std::numeric_limits<T>::max()); 

,並在同一個文件.HPP下面幾行執行:

template< 
    class T, 
    class> 
T InputReader::getIntegerTest(std::string& strErrorHint, 
           T nMinimumValue, 
           T nMaximumValue) 
{ 
    std::string strInputString; 
    std::cin >> strInputString; 

    // Do several checks 

    T nReturnValue = std::stoi(strInputString); /// <--- HERE!!! 

    // Do other checks on the returnValue 

    return nReturnValue; 
} 

現在的問題是,我想轉換我剛剛閱讀的字符串,我知道是在整數類型T的正確範圍內。我怎樣才能以好的方式做到這一點?

+1

'bool success = std :: cin >> T_instance;',then(another)range check ... – LogicStuff

+1

爲什麼不簡單使用'std :: istringstream'? –

回答

2

專門的函數對象是一種非常靈活的方式,可以根據類型特徵修改行爲。

的方法是:

  1. 定義一個通用模板,操作

  2. 專門爲極端案例模板

  3. 呼叫通過一個輔助函數

例如:

#include <iostream> 
#include <type_traits> 
#include <string> 


namespace detail { 
/// general case 
    template<class Integer, typename Enable = void> 
    struct convert_to_integer { 
     Integer operator()(std::string const &str) const { 
      return std::stoi(str); 
     } 
    }; 

// special cases 
    template<class Integer> 
    struct convert_to_integer<Integer, std::enable_if_t<std::is_same<long, Integer>::value> > { 
     long operator()(std::string const &str) const { 
      return std::stol(str); 
     } 
    }; 
} 

template<class T, class StringLike> 
T to_integral(StringLike&& str) 
{ 
    using type = std::decay_t<T>; 
    return detail::convert_to_integer<type>()(str); 
}; 

int main() { 

    std::string t1 = "6"; 
    const char t2[] = "7"; 

    std::cout << to_integral<int>(t1) << std::endl; 
    std::cout << to_integral<int>(t2) << std::endl; 

    // will use the specilaisation 
    std::cout << to_integral<long>(t1) << std::endl; 
    std::cout << to_integral<long>(t2) << std::endl; 

    // will use the default case 
    std::cout << to_integral<short>(t1) << std::endl; 
    std::cout << to_integral<short>(t2) << std::endl; 
} 

p.s.你的錯誤報告策略需要工作。建議投擲一個std::runtime_error

+0

謝謝你的答案@Richard Hodges!非常好!我非常感激!對於例外,爲什麼你認爲拋出異常而不是使用errorHint更好?特別是我想你會建議創建我自己的錯誤類型,並在失敗的情況下拋出該錯誤是否正確? – Francesco

+1

@ user2271691理想情況下,您自己的錯誤類型,派生自std :: runtime_error或來自std :: invalid_argument。 –

相關問題