标准无操作输出流

时间:2012-08-06 10:31:53

标签: c++ iostream

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

例如:

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

我可以创建一个ostringstream,但数据将被缓冲(我真的不想用它们做任何事情,所以它增加了无用的开销)。

有什么想法吗?

[edit] 找到符合我需求的related question。但是,我认为如何使用标准c ++创建一个有效(无badbit)输出流的答案会很有用。

6 个答案:

答案 0 :(得分:58)

您需要自定义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";

streambuf::overflow是缓冲区必须将数据输出到流的实际目标时调用的函数。

答案 1 :(得分:28)

如果这是为了禁用日志输出,那么dummyStream仍然会导致参数被评估。如果要在禁用日志记录时将影响降至最低,则可以依赖条件,例如:

#define debugStream \
    if (debug_disabled) {} \
    else std::cerr

所以如果您有以下代码:

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

如果debug_disabled为真,则不会评估任何参数。

答案 2 :(得分:3)

新流类的基本方法是:

  1. std::streambuf;
  2. 派生一个班级
  3. 覆盖该类中的虚函数。这是真正的工作所在。在您的情况下,空实现应该足够好。
  4. std::ostream派遣一名成员,即您的streambuf班。
  5. 您的streamclass的构造函数应该将指向该成员的指针转发给std :: ostream的基础构造函数。
  6. 但是,我担心你不会摆脱格式化步骤。

    希望这会给你一些指示;对不起,我没有时间将其扩展为完整答案。

    更新:有关详细信息,请参阅john's answer

答案 3 :(得分:0)

如果您担心调试器的开销,则可以编写一个非常简单的代码以使编译时的调试消息无效。这就是我在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 (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;
}

现在,在创建项目时,请检查用户是否要禁用日志记录,如果要禁用日志记录,只需取消定义DEBUGGING宏或您选择检查的任何宏即可。

现在您的代码将由编译器进行优化,因为当任何东西都作废时,它(大部分时间)将不包含在生成的二进制文件中,从而使二进制文件生产就绪。

答案 4 :(得分:0)

对于运行时可控制的日志消息重定向,这是一个结合了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

然后您可以执行以下操作:

TRACELN("The value of x is " << x " and the value of y is " << y);

仅使用#define跟踪宏到空语句完全从发行版中删除跟踪语句也很容易。

不过,您仍然需要在全局位置定义debug_stream

答案 5 :(得分:-1)

我需要一个类型为ostream的空流,所以我做了类似的事情:

struct NullStream: public stringstream {
   NullStream(): stringstream() {}
};

template<typename T>
void operator<<(const NullStream&, const T&) {}

申请代码:

NullStream ns;
ostream &os = ns;
os << "foo";

真正的问题是我继承的所有公共方法,但我并不关心所以我只是没有打扰它们。