2010-06-24 36 views
1

我想用C++模板創建一個簡單的整數範圍檢查器和轉換器。
的代碼看起來是這樣的:C++中的安全整數轉換

// D is the "destination" type and S the "source" type 
template <class D, class S> 
inline D SafeConvert(S value); 

template <class S> 
inline int SafeConvert<int>(S value) { 

    ASSERT(value >= S(INT_MIN) && value <= S(INT_MAX)); 
    return int(value); 
} /// error C2768: 'SafeConvert' : illegal use of explicit template arguments 


template <class S> 
inline size_t SafeConvert<size_t>(S value) { 

    ASSERT(value >= S(0) && value <= S(size_t(-1))); 
    return size_t(value); 
} /// error C2768: 'SafeConvert' : illegal use of explicit template arguments 


// ... 

void test() { 

    size_t v = INT_MAX+1; 
    int iv = SafeConvert<int>(v); 
} 

不過,我有以下來編譯錯誤:

error C2768: 'SafeConvert' : illegal use of explicit template arguments 

我的問題是如何告訴我要專注只有d類的編譯器?

謝謝。

+0

你可能想嘗試http://stackoverflow.com/questions/998571/c-template-for-safe-integer-casts/998982#998982 – 2010-06-26 15:17:46

回答

5

不能部分專門函數模板:

後者可以實現如下。你需要用類包裝器來模擬它,或者使用標準函數重載。 mimicing的例子:

template <typename T1, typename T2> 
struct processor; 

template < typename T1, typename T2 > 
T1 fun(T2 t2) { return processor<T1,T2>::apply(t2); } 

template < typename T2 > 
struct processor<int,T2> 
{ 
    static int apply(T2 t2) { .... } 
}; 

...etc... 
+0

或者只是使用一個庫。 – 2010-06-24 16:41:18

1

編寫一個結構SafeConverter<T, S>用於SafeConvert。比部分專業化更好的是使用std::numeric_limits,或者甚至是boost::numeric_cast,它已經以更復雜的方式實現了範圍檢查。

template<typename T, typename S> 
struct numeric_converter { 
    static T convert(const S& val); 
} 
template<typename T, typename S> 
T numeric_cast(const S& val) { 
    typedef numeric_converter<T, S> converter; 
    return converter::convert(val); 
} 
+1

我不會否定,因爲我幾乎說同樣的事情,但你應該先檢查你的答案。那麼你可能會想起爲什麼你不能這樣做。 – 2010-06-24 16:04:50

+0

與SO的問題是,答案彈出方式太快,所以我通常沒有時間在發帖之前思考我的答案,抱歉。 – Philipp 2010-06-24 16:10:30

0

只要寫SafeConvert<size_t, S>而不是SafeConvert<size_t>,我認爲,只有專業的第二個參數。 Noah Roberts在功能和類型的部分專業化方面也是正確的。

+0

其他方法,你想專門化第一個(目標)參數。 – 2010-06-24 16:23:54

+0

@Mike:謝謝,修正。 – 2010-06-24 21:19:35

4

這將是一個麻煩,地獄來維護。

通常我會建議使用numeric_limits

template <class D, class S> 
D SafeConvert(S value) 
{ 
    ASSERT(value >= std::numeric_limits<D>::min() 
     && value <= std::numeric_limits<D>::max()); 
    return static_cast<D>(value); 
} 

但是有每當你比較一個無符號的一個符號整數編譯器發出一個警告...(從來沒有真正的方式理解這一點)

因此,我建議使用Boost.NumericConversion,而不是重新發明輪子,特別是:boost::numeric_cast<>

當不需要檢查(即目標類型大於源類型)並且以其他方式執行必要的檢查時,它將保證性能免費。

+0

數字限制和boost :: numeric_cast是要走的路。 – Puppy 2010-06-24 21:23:09

+0

在S的最大值和D的最大值較大的情況下,這是否表明工作正常?或者將隱式轉換將其向一個方向擰緊? – 2012-07-29 17:56:11

+0

@JosephGarvin:我非常確信'boost :: numeric_cast'可以工作;)對於這裏介紹的自定義解決方案,恐怕我不知道內心的轉換。 – 2012-07-30 07:07:11