2010-06-29 31 views
5

警告我有,我相信是簡單修復,但我不知所措的問題...修復「比較始終是假的......」在GCC

我有一個模板,執行以下代碼:

T value  = d; 
if (std::numeric_limits<T>::is_signed) 
{ 
    if (value < 0) 
    { 
     *this += _T("-"); 
     value = -(signed)value; 
    } 
} 

現在的,原因很明顯,GCC是給我一個警告(比較總是由於數據類型的範圍有限假)時,該代碼被編譯爲一個無符號的類型。我完全理解這個背後的原因,並且我在numeric_limits檢查中查看是否可以讓編譯器關閉它(它對MSVC有效)。唉,在GCC下我得到了警告。有沒有什麼辦法可以解決這個警告?(缺少禁用我甚至不知道你是否可以用GCC做的警告)?代碼永遠不會被調用,我會認爲優化器也會將其編譯出來,但我無法擺脫警告。

有人可以給我一個解決方案嗎?

乾杯!

+2

當int是16位時,這是非常討厭的。當'value'很長時,'value = - (signed/* int * /)值會截斷較大的值。相反,乘以'-1',並讓優化器找出它。 – MSalters 2010-06-29 12:13:33

回答

5

簡單的解決方案:

template <typename T> inline bool isNegative(T value) { 
    return std::numeric_limits<T>::is_signed && value < 0; // Doesn't trigger warning. 
} 

T value  = d; 
if (isNegative(value)) // Doesn't trigger warning either. 
{ 
    *this += _T("-"); 
    value = -1 * value; 
} 
+0

不幸的是,儘管修復了gcc的警告,但它在MSVC上引入了一個新的警告,因爲當用無符號類型'(警告C4100:'值':未引用的形式參數)'調用isNegative'時,永遠不會使用參數'value'。令每一個編譯器都感到困難 - 禁用警告可能比編寫無處不在的代碼更好。 – 2010-06-29 12:37:05

+0

擴大到;我認爲您找到的每個解決方案都會導致編譯器警告,或者包含難以維護的複雜邏輯。 – 2010-06-29 12:40:39

+0

我想包裝'std :: numeric_limits :: is_signed'在函數模板中可能會刪除警告:'template bool is_signed(const T&){return std :: numeric_limits :: is_signed;}' - 但是,if它是這樣做的,它(如MSalters的版本)在運行時檢查中轉換編譯時檢查的成本___。最後,我可能會在VC之前關閉警告('#pragma warn(push:4100)',IIRC),之後再打開它('#pragma warn(pop)')。 – sbi 2010-06-29 13:25:47

3

有人可以給我一個解決方案嗎?

什麼都沒有革命性的,但我通常通過重載來做到這一點。類似的規定:

//Beware, brain-compiled code ahead! 
template< bool B > 
struct Bool { const static bool result = B; } 

template< typename T > 
void do_it(T& , Bool<false> /*is_signed*/) 
{ 
    // nothing to do for unsigned types 
} 

template< typename T > 
void do_it(T& value, Bool<true> /*is_signed*/) 
{ 
    if (value < 0) { 
     *this += _T("-"); 
     value = -(signed)value; 
    } 
} 

template< typename T > 
void do_something(T& value) 
{ 
    do_it(value, Bool<std::numeric_limits<T>::is_signed>()); 
} 

如果你可以使用類模板而不是函數模板,你可以用專業化,而不是超載。 (有沒有函數模板部分特例,這使得專業函數模板更麻煩的一點。)

+0

有點過於複雜 - 在bool和一個額外的調用參數中引入了編譯時包裝?另外,value的值需要改變,所以'value'需要通過非const引用傳遞。在使用'this'時,'T'可能是類的模板參數,而不是函數。 – 2010-06-29 11:18:09

+0

當我評論時,您的解決方案不會編譯,因爲您正在使用一個常量引用的變異值。我很抱歉,如果你解釋爲我的生活與你「惱火」。你也可能會注意到我沒有投下你的答案。 我對我評論的編輯是添加最後一句。 – 2010-06-29 12:19:15

+0

@Joe:那我一定誤解了你的評論,我對我的迴應表示歉意。我刪除了我的評論。 (你的評論與後來被證明是一個被刪除的最高票數的BTW一致),無論如何,關於'Bool <>'類型:我不會夢想嘗試編碼沒有在我的工具箱中的C++。它始終存在,我只需要在需要時抓住它。':)' – sbi 2010-06-29 13:27:49

2

你可以專注你的函數是這樣的:

template <bool S> 
void manipulate_sign(T&) {} 

template <> 
void manipulate_sign<true>(T& value) { 
    if (value < 0) 
    { 
    *this += _T("-"); 
    value = -(signed)value; 
    } 
} 

//then call like this: 
manipulate_sign<std::numeric_limits<T>::is_signed>(); 

只是禁用警告可能會更好,但。

+1

我肯定會包裝這個函數,所以用戶不必自己使用'numeric_limits' - 'T'是函數需要的所有信息:) – 2010-06-30 09:19:09