C++ 标准无操作输出流

C++ 标准无操作输出流,c++,iostream,C++,Iostream,有没有办法创建一个基本上什么都不做的ostream实例 例如: std::ostream dummyStream(...); dummyStream << "Nothing will be printed"; std::ostream dummyStream(…); dummyStream您需要自定义streambuf class NullBuffer : public std::streambuf { public: int overflow(int c) { return

有没有办法创建一个基本上什么都不做的ostream实例

例如:

std::ostream dummyStream(...);
dummyStream << "Nothing will be printed";
std::ostream dummyStream(…);

dummyStream您需要自定义streambuf

class NullBuffer : public std::streambuf
{
public:
  int overflow(int c) { return c; }
};
然后可以在任何ostream类中使用此缓冲区

NullBuffer null_buffer;
std::ostream null_stream(&null_buffer);
null_stream << "Nothing will be printed";
null缓冲区null\u缓冲区;
std::ostream空\u流(&null\u缓冲区);

null_stream如果这是为了禁用日志输出,则您的
dummyStream
仍将导致对参数求值。如果要在禁用日志记录时将影响降至最低,可以依赖条件,例如:

#define debugStream \
    if (debug_disabled) {} \
    else std::cerr
因此,如果您有如下代码:

debugStream << "debugging output: " << foo() << std::endl;

debugStream创建新流类的基本方法是:

  • std::streambuf
    派生一个类
  • 重写该类中的虚拟函数。这是真正的工作要做的地方。在您的情况下,空实现应该足够好了
  • std::ostream
    派生一个包含一个成员的类,即streambuf类
  • streamclass的构造函数应该将指向该成员的指针转发到std::ostream的基构造函数
  • 不过,恐怕您无法摆脱格式化步骤

    希望这能给你一些建议;对不起,我没有时间把这个问题扩展成一个完整的答案


    更新:有关详细信息,请参阅。

    我需要一个类型为ostream的空流,因此我执行了如下操作:

    struct NullStream: public stringstream {
       NullStream(): stringstream() {}
    };
    
    template<typename T>
    void operator<<(const NullStream&, const T&) {}
    
    struct NullStream:public stringstream{
    NullStream():stringstream(){}
    };
    模板
    
    void操作符如果您担心调试器的开销,那么您可以编写一个非常简单的代码,在编译时消除调试消息。这是我用C++程序编写的。
    #include <iostream>
    #define DEBUGGING // Define this in your config.h or not.
    #ifdef DEBUGGING
    /*
     * replace std::cout with your stream , you don't need to
     * worry about the context since macros are simply search
     * and replace on compilation.
     */
    #define LOG_START std::cout <<
    #define LOG_REDIR <<
    #define LOG_END   << std::endl;
    #else
    #define LOG_START if(0){(void)
    #define LOG_REDIR ;(void)
    #define LOG_END   ;}
    #endif // DEBUGGING
    
    int main(){
    LOG_START "This is a log message " LOG_REDIR "Still a log message." LOG_END;
    return 0;
    }
    
    #包括
    #定义调试//是否在config.h中定义调试。
    #ifdef调试
    /*
    *用流替换std::cout,您不需要
    *担心上下文,因为宏只是搜索
    *并在编译时替换。
    */
    
    #为日志消息的运行时可控重定向定义LOG_START std::cout,这是一个结合john和Sjoerd思想的自包含解决方案:

    class DebugStream {
    private:
        class NullStream : public std::ostream {
        private:
            class NullBuffer : public std::streambuf {
            public:
                int overflow(int c) override { return c; }
            } buffer_;
        public:
            NullStream() : std::ostream(&buffer_) {}
        } null_;
    
        std::ostream &output_;
        bool enabled_;
    
    public:
        DebugStream(std::ostream &output = std::cout) : output_(output), enabled_(false) {}
        void enable(const bool enable) { enabled_ = enable; }
    
        template <typename T> std::ostream& operator<<(const T &arg) {
            if (enabled_) return output_ << arg;
            else return null_ << arg;
        }
    };
    
    extern DebugStream debug_stream;
    #define TRACE_ENABLE(x) debug_stream.enable(x)
    #define TRACELN(x) debug_stream << x << std::endl
    #define TRACE(x) debug_stream << x
    
    类调试流{
    私人:
    类NullStream:public std::ostream{
    私人:
    类NullBuffer:public std::streambuf{
    公众:
    int溢出(int c)重写{return c;}
    }缓冲区;
    公众:
    NullStream():std::ostream(&缓冲区{}
    }空值(0);;
    std::ostream&output;
    bool-enabled;
    公众:
    DebugStream(std::ostream&output=std::cout):输出(output),已启用(false){
    void enable(const bool enable){enabled_u=enable;}
    
    模板std::ostream&operatorI被指向。Boost.Iostreams
    是选项吗?可以创建一个方便的类
    类NullStream:public std::ostream{public:NullStream():std::ostream(&m_sb){}private:NullBuffer m_sb;};
    ,这将用法简化为
    NullStream null\u stream;null\u stream这太棒了,我建议添加@Sjoerd的建议。我实现了一些与他的建议完全相同的东西,直到我回到upvote时才看到他的评论。只是一个问题:函数可能会导致失败,将流变成失败状态(不过,大多数人不会在意)。为了避免这种情况,您需要返回
    not_eof()的结果。此外,缓冲字符比在假定不太可能的路径上调用
    virtual`函数更有效,也就是说,我还建议添加一个被忽略的缓冲区。覆盖将变成
    int溢出(intc){返回this->setp(std::begin(d_buffer),std::end(this->d_buffer);std::char_traits::not_eof(c);}
    。同样,覆盖
    xsputn()也是合理的
    什么也不做。@DietmarKühl:你介意将其编辑到答案中,还是写下你自己的答案?我很抱歉回答了这个问题,但我真的需要知道:这个答案在性能方面是否比选择的答案更好?如果debug_disabled是一个常量(或者更合适的宏),编译器可能(会?)优化else子句,而使用nullbuffer仍然会导致流输入被处理,只会被放入一个空设备。这是真的吗?还是假的?如果有人能帮我解释一下,那就太棒了。@bobismijnnaam:事实上,在我发布它的那天晚些时候,有人在一个问题中剽窃了这个答案:-).Hmm,不管怎样,我还是同意你的答案。整个NullStream的工作似乎太多了。这是一个很好的解决方案,但是有没有可能在不包含
    iostream
    或定义一次性全局变量的情况下做类似的事情?@Paul:问题是关于使用
    ostream
    ,我只是选择了一个已经读过的y可用。若要禁用日志记录,日志行必须位于
    else
    侧。因此,如果目标是始终禁用,只需使用
    true
    而不是变量。编译器不会优化out函数调用。您需要将log_START定义为
    if(0){(void)
    ,而log_END定义为
    }
    。即使禁用了优化功能,也会对其进行优化-至少gcc在使用-O0编译时能够这样做。@DanielFrużyński感谢您的提示。我已经做了更改。
    class DebugStream {
    private:
        class NullStream : public std::ostream {
        private:
            class NullBuffer : public std::streambuf {
            public:
                int overflow(int c) override { return c; }
            } buffer_;
        public:
            NullStream() : std::ostream(&buffer_) {}
        } null_;
    
        std::ostream &output_;
        bool enabled_;
    
    public:
        DebugStream(std::ostream &output = std::cout) : output_(output), enabled_(false) {}
        void enable(const bool enable) { enabled_ = enable; }
    
        template <typename T> std::ostream& operator<<(const T &arg) {
            if (enabled_) return output_ << arg;
            else return null_ << arg;
        }
    };
    
    extern DebugStream debug_stream;
    #define TRACE_ENABLE(x) debug_stream.enable(x)
    #define TRACELN(x) debug_stream << x << std::endl
    #define TRACE(x) debug_stream << x
    
    TRACELN("The value of x is " << x " and the value of y is " << y);