2010-06-29 21 views
5

में चेतावनी मैं एक समस्या जो मुझे यकीन है कि ठीक करने के लिए सरल है, लेकिन मैं एक नुकसान में हूँ हूँ ...फिक्सिंग "तुलना हमेशा गलत है ..." जीसीसी

आ रही है मैं एक टेम्पलेट है निम्नलिखित कोड करता है:

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

अब के लिए, स्पष्ट कारणों, जीसीसी मुझे एक चेतावनी दे रहा है जब इस कोड को एक अहस्ताक्षरित प्रकार के लिए संकलित किया गया है (तुलना हमेशा डेटा प्रकार की सीमित रेंज की वजह से गलत है)। मैं इसके पीछे तर्क को पूरी तरह से समझता हूं और मैंने संख्यात्मक_लिमिट्स चेक में यह देखने के लिए जांच की है कि क्या मैं इसके बारे में बंद करने के लिए कंपाइलर प्राप्त कर सकता हूं (यह एमएसवीसी के लिए काम करता है)। जीसीसी के तहत मुझे चेतावनी मिलती है। क्या इस चेतावनी को ठीक करने के लिए कोई तरीका है (चेतावनी को अक्षम करने से कम जिसे मैं यह भी नहीं जानता कि आप जीसीसी के साथ क्या कर सकते हैं)? कोड को वैसे भी कभी नहीं बुलाया जाएगा और मुझे लगता है कि ऑप्टिमाइज़र इसे भी संकलित करेगा लेकिन मैं चेतावनी से छुटकारा नहीं पा सकता हूं।

क्या कोई मुझे इसका समाधान दे सकता है?

चीयर्स!

+2

यह बहुत बुरा है जब 'int' 16 बिट्स है। जब 'मान' लंबा होता है, तो' value = - (हस्ताक्षरित/* int * /) मान 'बड़े मानों को छोटा करता है। इसके बजाय '-1' गुणा करें, और ऑप्टिमाइज़र इसे समझने दें। – MSalters

उत्तर

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

दुर्भाग्यवश, जबकि यह जीसीसी पर चेतावनी को हल करता है, यह एमएसवीसी पर एक नई चेतावनी पेश करता है क्योंकि 'निष्क्रिय' पैरामीटर 'मान' का उपयोग कभी नहीं किया जाता है जब एक हस्ताक्षरित प्रकार' (चेतावनी C4100: 'मान': अप्रतिबंधित औपचारिक पैरामीटर) के साथ बुलाया जाता है। हर कंपाइलर को प्रसन्न करना मुश्किल है - यह कोड लिखने की तुलना में चेतावनी को अक्षम करना बेहतर हो सकता है जो हर जगह साफ-सुथरा संकलित करता है। –

+0

उसमें विस्तार करने के लिए; मुझे लगता है कि आपको जो भी समाधान मिलेगा वह या तो एक कंपाइलर चेतावनी का कारण बनता है या अन्य में घुलनशील तर्क होता है जो बनाए रखना अधिक कठिन होगा। –

+0

मुझे लगता है कि एक कार्य टेम्पलेट में 'std :: numeric_limits :: is_signed' को लपेटने का मानना ​​है: चेतावनी: टेम्पलेट बूल is_signed (कॉन्स्ट टी एंड) {वापसी std :: numeric_limits :: is_signed;} '- हालांकि, अगर ऐसा करता है, यह (एमएसल्टर्स संस्करण के रूप में) यह एक रन-टाइम चेक__ में संकलन-समय की जांच को चालू करने की लागत को __at करता है। अंत में मैं शायद वीसी ('#pragma चेतावनी (पुश: 4100) ', आईआईआरसी) में चेतावनी बंद कर दूंगा, और बाद में इसे वापस चालू कर दूंगा (' #pragma चेतावनी (पॉप) ')। – sbi

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

थोड़ा अधिक जटिल - बूल के चारों ओर एक संकलन समय रैपर और कॉल के लिए एक अतिरिक्त पैरामीटर पेश करना? साथ ही, 'मान' को गैर-कॉन्स्ट संदर्भ द्वारा पारित करने की आवश्यकता है, क्योंकि इसका मूल्य बदल जाता है। चूंकि यह 'इस' का उपयोग कर रहा है,' टी' शायद वर्ग का टेम्पलेट पैरामीटर है, फ़ंक्शन नहीं। –

+0

जब मैंने टिप्पणी की, तो आपका समाधान संकलित नहीं होगा क्योंकि आप एक उत्परिवर्तित मूल्य के लिए एक कॉन्स्ट संदर्भ का उपयोग कर रहे हैं। मुझे खेद है कि अगर आप इसे मेरे साथ 'परेशान' के रूप में समझते हैं। आप यह भी ध्यान दें कि मैंने आपके जवाब को वोट नहीं दिया है। मेरी टिप्पणी में किए गए संपादन को अंतिम वाक्य जोड़ना था। –

+0

@ जो: फिर मैंने आपकी टिप्पणी को गलत तरीके से पढ़ा होगा और मैं अपनी प्रतिक्रिया के लिए क्षमा चाहता हूं। मैंने अपनी टिप्पणी हटा दी। (आपकी टिप्पणी के साथ बाद में एक हटाए गए अप-वोट, बीटीडब्ल्यू के रूप में सामने आया, जिसे पहले मैंने डाउन-वोट के रूप में लिया था।) वैसे भी, 'बूल <>' प्रकार के बारे में: मैं कोड को आजमाने का सपना नहीं देखूंगा मेरे टूलबॉक्स में इसके बिना सी ++। यह हमेशा वहाँ होता है और मुझे इसकी आवश्यकता होने पर इसे पकड़ने की आवश्यकता होती है।':)' – sbi

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' स्वयं का उपयोग न करना पड़े- 'टी' फ़ंक्शन की सभी जानकारी की आवश्यकता है :) –

3

वास्तविक समाधान है, जो दबा -Wtype सीमा की अनुमति देता है के लिए https://stackoverflow.com/a/8658004/274937 देखें चेतावनी मामला-दर-मामला। संक्षेप में, बस प्रत्येक तुलना को लपेटें, जो चेतावनी उत्पन्न करता है, एक डमी फ़ंक्शन में।

संबंधित मुद्दे