簡體   English   中英

實現no-op std :: ostream

[英]Implementing a no-op std::ostream

我正在尋找一個日志類,其中包含Info,Error等成員,可以配置輸出到控制台,文件或無處。

為了提高效率,我希望避免格式化將被丟棄的消息(即未在詳細模式下運行時的信息消息)的開銷。 如果我實現一個輸出到無處的自定義std :: streambuf,我想std :: ostream層仍將執行所有格式化。 任何人都可以建議一種方法來擁有一個真正的“空”std :: ostream,它可以避免在使用<<傳遞給它的參數上做任何工作嗎?

一個快速的谷歌想出了這個可能有用的例子。 除了編譯和運行之外,我不提供任何保證:-)

#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;
}

所有,感謝分享代碼,我只是做一個測試,然后Neil的方法仍然會進行字符串格式化,例如:

#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&operator <<(ostream&out,MyClass const&b)”將被調用。 因此,仍然會調用obj上的格式。 因此,我們仍然無法避免格式化消息的開銷。

要防止operator<<()調用進行格式化,您應該在編譯時知道streamtype。 這可以使用宏或使用模板完成。

我的模板解決方案如下

class NullStream {
public:
    void setFile() { /* no-op */ }
    template<typename TPrintable>
    NullStream& operator<<(TPrintable const&)
    { return *this; } /* 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
}

由於您必須在編譯時執行此操作,因此它當然非常不靈活。

例如,您無法從配置文件中確定運行時的日志記錄級別。

可能你需要的不僅僅是文本格式和消息過濾。 多線程怎么樣?

我將實現過濾和多線程同步作為單獨類的責任。

但是,日志記錄是一個不那么簡單的問題,我會嘗試使用現有的日志記錄解決方案,而不是開發新的日志記錄解決方案。

為什么不使用數百萬用戶使用的現有日志解決方案? log4j,log4net,log4cxx ..,僅舉幾例..

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM