2009-04-17 11 views
30

लागू करने के लिए मैं एक लॉगिंग क्लास बनाना चाहता हूं जिसमें जानकारी, त्रुटि इत्यादि जैसे सदस्य हैं जो कॉन्फ़िगरेशन, फ़ाइल या कहीं भी कॉन्फ़िगर करने के लिए आउटपुट कर सकते हैं।नो-ऑप std :: ostream

दक्षता के लिए, मैं उन संदेशों को फेंक दिया जा करने के लिए (यानी की जानकारी संदेशों एक वर्बोज़ मोड में जब नहीं चल) जा रहे स्वरूपण की भूमि के ऊपर से बचने के लिए चाहते हैं। यदि मैं एक कस्टम std :: streambuf को लागू करता हूं जो कहीं भी आउटपुट नहीं करता है, तो मुझे लगता है कि std :: ostream परत अभी भी सभी स्वरूपण करेगा। क्या कोई वास्तव में "शून्य" std :: ostream होने का एक तरीका सुझा सकता है जो << के साथ पारित पैरामीटर पर किसी भी काम को करने से बचाता है?

धन्यवाद।

+0

मुझे चिंता नहीं होगी। नील द्वारा दिखाए गए एक नल स्ट्रीम का उपयोग करें। कक्षा को किसी भी बेहतर प्रदर्शन की आवश्यकता नहीं है, क्योंकि जाहिर है कि यदि आपके पास शून्य लक्ष्य नहीं है, तो प्रारूपण * किया जाना है, इसलिए यह स्पष्ट रूप से महत्वपूर्ण नहीं है। बस मेरे 2 सेंट –

+0

हम्म, लेकिन ऐसा लगता है कि यह "डीबग आउटपुट" चीज़ के रूप में है? एक तरीका मैंने देखा है इस तरह है: बाहर() << एक << बी ...; और बाहर() संरचना एफ {} लौटाता है; टेम्पलेट होने के साथ एफ कॉन्स और ऑपरेटर << (एफ कॉन्स और एफ_, टी कॉन्स) {वापसी f_; }, और फिर लॉग स्तर के आधार पर अलग-अलग structs को वापस कर दें। या अलग-अलग कार्यों या जो भी हो। –

उत्तर

4

स्वरूपण करने से operator<<() आमंत्रण रोकने के लिए, आप संकलन समय पर streamtype पता होना चाहिए। यह या तो मैक्रोज़ या टेम्पलेट्स के साथ किया जा सकता है।

मेरा टेम्पलेट समाधान निम्नानुसार है।

class NullStream { 
public: 
    void setFile() { /* no-op */ } 
    template<typename TPrintable> 
    NullStream& operator<<(TPrintable const&) 
    { /* no-op */ } 
} 

template<class TErrorStream> // add TInfoStream etc 
class Logger { 
public: 
    TErrorStream& errorStream() { 
     return m_errorStream; 
    } 

private: 
    TErrorStream m_errorStream; 
}; 

//usage 
int main() { 
    Logger<std::ofstream> normal_logger; // does real output 
    normal_logger.errorStream().open("out.txt"); 
    normal_logger.errorStream() << "My age is " << 19; 

    Logger<NullStream> null_logger; // does zero output with zero overhead 
    null_logger.errorStream().open("out.txt"); // no-op 
    null_logger.errorStream() << "My age is " << 19; // no-op 
} 

चूंकि आपको संकलन समय पर ऐसा करना है, यह निश्चित रूप से काफी लचीला है।

उदाहरण के लिए, आप कॉन्फ़िगरेशन फ़ाइल से रनटाइम पर लॉगिंग स्तर का निर्धारण नहीं कर सकते हैं।

+0

+1: सरल, साफ, अच्छी तरह से काम करता है। ध्यान दें कि उदा।"नलस्ट्रीम एस; एस << महंगा_फंक्शन();" सबसे अधिक संभावना है कि अभी भी महंगा_फंक्शन() का मूल्यांकन करें, खासकर यदि यह किसी अन्य मॉड्यूल में रहता है। –

+3

मैं यह भी उल्लेख करूंगा कि, नील के ऑनस्टस्ट्रीम के विपरीत, आपके नलस्ट्रीम को ओस्ट्रीम और ओस्ट्रीम * तर्क की अपेक्षा रखने वाले फ़ंक्शन पर नहीं भेजा जा सकता है। –

+0

महंगा_फंक्शन() _definitely_ का मूल्यांकन किया जाएगा चाहे वह कहाँ रहता है। मैक्रोज़ और सशर्त संकलन को छोड़कर परेशान करने का कोई तरीका नहीं है :) ... नील के ऑनस्टस्ट्रीम के रूप में, मुझे विश्वास नहीं है कि यह "शून्य स्वरूपण ओवरहेड" आवश्यकता को पूरा करता है :) –

0

शायद आपको केवल टेक्स्ट स्वरूपण और संदेश फ़िल्टरिंग से अधिक की आवश्यकता होगी। मल्टीथ्रेडिंग के बारे में क्या?

मैं एक अलग वर्ग की जिम्मेदारी के रूप में छानने और बहु ​​सूत्रण तुल्यकालन लागू करेगा।

हालांकि, प्रवेश एक नहीं तो साधारण सी समस्या है, और मैं बजाय एक नया एक विकसित करने की, मौजूदा प्रवेश समाधान का उपयोग करने की कोशिश करेगा।

15

एक तेज Google इस उदाहरण के साथ आया जो उपयोग में हो सकता है। मैं कोई गारंटी प्रदान करते हैं, सिवाय इसके कि यह संकलित करता है तथा :-)

#include <streambuf> 
#include <ostream> 

template <class cT, class traits = std::char_traits<cT> > 
class basic_nullbuf: public std::basic_streambuf<cT, traits> { 
    typename traits::int_type overflow(typename traits::int_type c) 
    { 
     return traits::not_eof(c); // indicate success 
    } 
}; 

template <class cT, class traits = std::char_traits<cT> > 
class basic_onullstream: public std::basic_ostream<cT, traits> { 
    public: 
     basic_onullstream(): 
     std::basic_ios<cT, traits>(&m_sbuf), 
     std::basic_ostream<cT, traits>(&m_sbuf) 
     { 
      init(&m_sbuf); 
     } 

    private: 
     basic_nullbuf<cT, traits> m_sbuf; 
}; 

typedef basic_onullstream<char> onullstream; 
typedef basic_onullstream<wchar_t> wonullstream; 

int main() { 
    onullstream os; 
    os << 666; 
} 
+0

+1। हां, मुझे लगता है कि std :: basic_ostream <> से प्राप्त करना जरूरी है यदि आप एक ओस्ट्रीम और ओस्ट्रीम * पैरामीटर की अपेक्षा करने वाले फ़ंक्शन में एक डू-कुछ स्ट्रीम पास करना चाहते हैं - ईरिंबिलानजा की चाल वहां काम नहीं करेगी। –

+0

इसे केवल 'ओस्ट्रीम *' के रूप में स्वीकार किया जा सकता है, न कि 'ओस्ट्रीम' ', सही है? – athos

0

क्यों उपयोगकर्ताओं के लाखों लोगों द्वारा प्रयोग किया जाता मौजूदा प्रवेश समाधान का उपयोग नहीं चलाता है? log4j, log4net, log4cxx .., बस कुछ उदाहरण .. को

13

सब, धन्यवाद कोड साझा करने के लिए, मैं सिर्फ एक परीक्षण करते हैं, तो नील की पद्धति अभी भी स्ट्रिंग formating, उदाहरण के लिए क्या करेंगे:

#include <streambuf> 
#include <ostream> 
#include <iostream> 
using namespace std; 


template <class cT, class traits = std::char_traits<cT> > 
class basic_nullbuf: public std::basic_streambuf<cT, traits> { 
    typename traits::int_type overflow(typename traits::int_type c) 
    { 
     return traits::not_eof(c); // indicate success 
    } 
}; 

template <class cT, class traits = std::char_traits<cT> > 
class basic_onullstream: public std::basic_ostream<cT, traits> { 
    public: 
     basic_onullstream(): 
     std::basic_ios<cT, traits>(&m_sbuf), 
     std::basic_ostream<cT, traits>(&m_sbuf) 
     { 
      init(&m_sbuf); 
     } 

    private: 
     basic_nullbuf<cT, traits> m_sbuf; 
}; 

typedef basic_onullstream<char> onullstream; 
typedef basic_onullstream<wchar_t> wonullstream; 

class MyClass 
{ 
    int a; 
    friend ostream& operator<< (ostream&, MyClass const&); 
}; 

ostream& operator<<(ostream& out,MyClass const& b) 
{ 
    std::cout<<"call format function!!"; 
    out << b.a; 
    return out; 
} 

int main() { 
    onullstream os; 
    MyClass obj; 
    os<<obj; 
} 

इस कार्यक्रम चल रहा है, तो आप पाएंगे कि "ostream & ऑपरेटर < < (ostream & बाहर, MyClass स्थिरांक & ख)" कहा जाएगा। तो, ओबीजे पर प्रारूप करना अभी भी कहा जाएगा। इसलिए, हम अभी भी स्वरूपण संदेशों के ऊपरी हिस्से से नहीं बच सकते हैं।

+0

AFAIK ऑप्टिमाइज़र कोड को हटा सकता है जिसे माना जाता है कि इसका दुष्प्रभाव नहीं है। चूंकि आपका कॉल 'std :: cout <<" कॉल प्रारूप फ़ंक्शन !! "है," साइड इफेक्ट्स हैं, तो ऑप्टिमाइज़र इसे हटा नहीं देगा। हालांकि, कॉल के बिना, यह संभव है कि इसे हटा दिया जाएगा –

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