2012-08-12 11 views
9

मेरे कार्यक्रम में मैं उन आवेषणों का उपयोग करना चाहता हूं जो एक त्रुटि संदेश दिखाते हैं। इसके अलावा सी और सी के लिए अच्छी तरह से ज्ञात समाधान ++ से वहाँ 'असली' समाधान के रूप में बूस्ट BOOST_ASSERT_MSG(expr, msg) प्रदान करता है (यह भी assert() with message देखें)गतिशील संदेश के साथ जोर दें?

लेकिन एक स्थिर संदेश मेरे लिए काफी नहीं है, मैं भी कभी कभी विफल रहा है चर दिखाना चाहते हैं, जैसे जैसे

BOOST_ASSERT_MSG(length >= 0, "No positive length found! It is " << length) 

एक मामले में आप देख सकते हैं मैं एक stringstream या ostream कि के रूप में के रूप में संदेश "स्ट्रिंग" फ़ॉर्मेट करने के लिए मुझे आसानी से कस्टम प्रकार (दिखाए जाने की अनुमति चाहता हूँ करना चाहते हैं यह मानते हुए कि मैं प्रासंगिक परिभाषित किया है फॉर्मेटिंग फ़ंक्शन)।

समस्या यह है कि BOOST_ASSERT_MSG डिफ़ॉल्ट रूप से char const * की आवश्यकता है ताकि यह संगत न हो।

क्या assertion_failed_msg() को फिर से परिभाषित/ओवरलोड करने का कोई तरीका है जिससे संदेश के रूप में स्ट्रीम का उपयोग किया जाएगा? कैसे?
(मेरे अनुभवहीन दृष्टिकोण में विफल रहा है के रूप में संकलक पहले संदेश पर ही एक operator<<("foo",bar) करना चाहता था ...)

उत्तर

6

आप निर्धारित कर सकते हैं अपने खुद के मैक्रो

#define ASSERT_WITH_MSG(cond, msg) do \ 
{ if (!(cond)) { std::ostringstream str; str << msg; std::cerr << str.str(); std::abort(); } \ 
} while(0) 
+0

है क्यों 'जबकि (0)'? – WiSaGaN

+1

कृपया देखें http://stackoverflow.com/questions/1067226/c-multi-line-macro-do-while0-vs-scope-block – Greg

+1

यदि आप 'जबकि (0)' का उपयोग करते हैं, तो ';' को छोड़ दें। –

5

यह इस लक्ष्य को हासिल करने के लिए अपेक्षाकृत मामूली है।

BOOST_ASSERT_MSG(length >= 0, (std::stringstream() << "No positive length found! It is " << length).str().c_str()) 
+4

मुझे ऐसा करने की उम्मीद है, लेकिन संकलक शिकायत करता है: 'त्रुटि:' स्ट्रक्चर std :: basic_ostream 'का कोई सदस्य नहीं है' str'' – Chris

+3

ओह, हाँ। मैं भूल रहा हूं कि स्ट्रिंगस्ट्रीम lib कैसे टूटा हुआ है। – Puppy

+0

आपको 'std :: stringstream :: str()' का उपयोग करने में सक्षम होने के लिए 'static_cast () '' ऑपरेटर <<() 'का वापसी मान होना चाहिए। अन्यथा आप 'std :: ostream :: str() 'को कॉल करने का प्रयास कर रहे हैं, जो मौजूद नहीं है। – Ruslan

1

मैं इसे चारों ओर मेरे अपने आवरण के साथ BOOST_ASSERT_MSG उपयोग करते हैं, तो यह है कि कई operator<< साथ ज़ोर संदेश को निर्दिष्ट कम जटिल लगता है। ,

ASSERT(execSize == (_oldSize - remaining), "execSize : " << execSize << ", _oldSize : " << _oldSize << ", remaining : " << remaining); 

यह है क्या करता है, तो ASSERT_ENABLED परिभाषित किया गया है, अभिकथन संदेश सक्षम:

#if defined ASSERT_ENABLED 

    #define ASSERT(cond, msg) {\ 
     if(!(cond))\ 
     {\ 
      std::stringstream str;\ 
      str << msg;\ 
      BOOST_ASSERT_MSG(cond, str.str().c_str());\ 
     }\ 
    } 
#else 
    #define ASSERT(...) 
#endif 

के उपयोग का उदाहरण, कस्टम संदेश प्रदान की तरह आप cout करने के लिए outputting रहे हैं। if(!(cond)) हिस्सा अनुकूलन है, जो मैक्रो पैरामीटर msg द्वारा निर्दिष्ट महंगा स्ट्रिंग आपरेशन से बचा जाता है, अगर condtrue

+0

क्या आपको वास्तव में '#if परिभाषित ASSERT_ENABLED' की आवश्यकता है? मुझे लगता है कि अगर जोर अक्षम है, तो अनुकूलन कंपाइलर का उपयोग करते हुए, कथन को वैसे भी हटा दिया जाता है। क्या मैं सही हूँ? –

+0

@ सोहेलसी: हां, '#if परिभाषित ASSERT_ENABLED' ऑप्टिमाइज़ेशन के लिए है। आम तौर पर रिहाई का निर्माण दावे के साथ होने के लिए किया जाता है। यह बाइनरी से कोड हटा देता है। छोटे बाइनरी, कम कोड, निर्देश कैश का बेहतर उपयोग। जबकि assert डीबगिंग में बहुत समय बचाता है। कभी-कभी, एक सरल जोर से जांच 3 दिनों के डिबगिंग समय को बचा सकता है। –

+0

मेरा मतलब है कि यदि ASSERT_ENABLED परिभाषित किया गया है तो संकलक को स्वचालित रूप से BOOST_ASSERT_MSG कथन को हटा देना चाहिए, इसलिए अपने शेष जोर कोड को हटा देना चाहिए। तो स्पष्ट रूप से जांचने के लिए ASSERT_ENABLED आवश्यक नहीं है। लेकिन मुझे यकीन नहीं है कि स्पष्ट रूप से कहा जाने की आवश्यकता क्यों है।मैं कहाँ गलत हूँ? –

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