हां, लेकिन आपको शायद एक और चेतावनी मिल जाएगी।
ऐसा करने का मानक तरीका यह है: (void)iid;
।
बहुत तकनीकी रूप से, यह अभी भी एक रजिस्टर में iid
लोड और कुछ भी नहीं कर सकता है। यह माना जाता है कि यह कंपाइलर्स भाग पर बेहद बेवकूफ है (मुझे संदेह है कि कोई भी ऐसा करेगा, अगर यह कंपाइलर को हटा देता है), लेकिन अगर अभिव्यक्ति को अनदेखा किया जाए तो यह एक और गंभीर मुद्दा है, आईओ कार्यों को कॉल करने जैसे अवलोकन योग्य व्यवहार से संबंधित कुछ है या volatile
चर के पढ़ने और लिखना।
यह एक दिलचस्प सवाल लाता है: क्या हम एक अभिव्यक्ति ले सकते हैं और पूरी तरह से इसे अनदेखा कर सकते हैं?
है यही कारण है, कि हम क्या अब यह है:
#define USE(x) (void)(x)
// use iid in an expression to get rid of warning, but have no observable effect
USE(iid);
// hm, result of expression is gone but expression is still evaluated
USE(std::cout << "hmmm" << std::endl);
यह एक समाधान के करीब है:
// sizeof doesn't evaluate the expression
#define USE(x) (void)(sizeof(x))
लेकिन साथ विफल:
void foo();
// oops, cannot take sizeof void
USE(foo());
समाधान बस है:
// use expression as sub-expression,
// then make type of full expression int, discard result
#define USE(x) (void)(sizeof((x), 0))
जो कोई ऑपरेशन की गारंटी देता है।
संपादित करें: ऊपर वास्तव में कोई प्रभाव नहीं की गारंटी है, लेकिन मैं परीक्षण के बिना पोस्ट। परीक्षण पर, यह कम से कम एमएसवीसी 2010 में एक चेतावनी उत्पन्न करता है, क्योंकि मान का उपयोग नहीं किया जाता है। यह कोई अच्छा नहीं है, अधिक चाल के लिए समय!
अनुस्मारक: हम इसका मूल्यांकन किए बिना अभिव्यक्ति का "उपयोग" करना चाहते हैं।यह कैसे किया जा सकता है? इस तरह:
#define USE(x) ((void)(true ? 0 : (x)))
यह आखिरी बार (वास्तव में बदतर) की तरह एक साधारण समस्या है, कि (x)
जरूरतों में int
के लिए परिवर्तनीय हो सकता है। यह फिर से ठीक करने के लिए है, तुच्छ:
#define USE(x) ((void)(true ? 0 : ((x), 0)))
और हम हम पिछली बार (कोई नहीं) था प्रभाव का एक ही तरह के वापस आ गए हैं, लेकिन इस बार x
"पुराना" है तो हम कोई चेतावनी नहीं मिलता । सही किया?
वास्तव में इस समाधान के साथ अभी भी एक समस्या (पिछले अन-समाधान में उपहार के रूप में अच्छी तरह से और था, लेकिन ध्यान नहीं दिया गया) है, और यह इस उदाहरण में ऊपर आता है:
struct foo {};
void operator,(const foo&, int) {}
foo f;
USE(f); // oops, void isn't convertible to int!
यही है, अगर (x)
अभिव्यक्ति का प्रकार अल्पविराम ऑपरेटर को int
में कनवर्ट करने योग्य नहीं है, समाधान विफल हो जाता है। बेशक, संभावना नहीं है, लेकिन पूरी तरह से पानी में गिर जाने के लिए, हम इसके साथ ठीक कर सकते हैं:
#define USE(x) ((void)(true ? 0 : ((x), void(), 0)))
यकीन है कि हम वास्तव में शून्य के साथ खत्म करने के लिए। This trick brought to you by Johannes।
के रूप में भी बताया गया है, यदि ऊपर पर्याप्त नहीं था, एक मूर्ख पर्याप्त संकलक संभावित "लोड" अभिव्यक्ति 0
(एक रजिस्टर या कुछ में), तो यह उपेक्षा कर सकता है।
मुझे लगता है कि इससे छुटकारा पाना असंभव है, क्योंकि आखिरकार हमें अनदेखा करने के लिए किसी प्रकार का एक अभिव्यक्ति की आवश्यकता होती है, लेकिन यदि मैंने कभी इसके बारे में सोचा है तो मैं इसे जोड़ूंगा।
क्या यह "कथन का कोई प्रभाव नहीं पड़ता" चेतावनी नहीं देगा? – falstro
@roe: यह विजुअल सी ++ पर नहीं है। शायद यह कुछ अन्य कंपाइलर्स पर करता है। – sharptooth
अगर घोषणा और कथन के बीच आप प्रीप्रोसेसर का दुरुपयोग करते हैं तो इसका असर हो सकता है। उदाहरण के लिए '#define variableName निकास (-1) ' – Benoit