【问题标题】:Doubling a stream加倍流
【发布时间】:2011-11-12 05:19:37
【问题描述】:

我将 cerr 流用于我的错误输出,但我也想将任何错误输出保存在内存中的字符串流中。

我想把这个变成:

stringstream errorString;
cerr << " Something went wrong ";
errorString << " Something went wrong ";

进入

myErr << " Something went wrong ";

其中 myErr 是一个类的实例,该类将其存储在字符串流中并输出到 cerr。

感谢您的帮助。

【问题讨论】:

  • 您想支持 ostreams 也支持的所有类型吗?
  • 这是最好的情况,它只是想成为 cerr 的替代品。但我不确定这会涉及多少工作。

标签: c++ stream


【解决方案1】:

在您的 MyErr 类中覆盖 operator&lt;&lt;

MyErr& operator<< ( MyErr& myErr, std::string message)
{
    cerr << message;
    errorString << message; //Where errorString is a member of the MyErr class

    return myErr;
}

那么你要在哪里记录错误:

int main()
{
    MyErr myErr;
    myErr << " Something went wrong. ";

    return 0;
}

您可能希望将MyErr 设为单例类,以便写入errorString 的所有内容都在一个位置。

【讨论】:

  • 一个简单的覆盖不会启用流“堆叠”,我很困惑如何覆盖它来做到这一点。
  • 正如@Daniel 所说,创建一个类并覆盖运算符cerr<< 和 errorString&lt;&lt;
  • 我冒昧地更改了您代码中的小错字错误……
  • @Konrad:谢谢。我整天都在 C# 模式下。
  • 这仅适用于字符串。您需要为要输出的每一种类型编写覆盖。
【解决方案2】:

使用Boost tee

【讨论】:

  • 我正在输入一些关于如何编写自己的 tee 类的内容。我应该记得 boost 有一个。愚蠢的工具包。
【解决方案3】:

您可以使用Boost.IOStreams

#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/stream.hpp>
#include <iostream>
#include <sstream>

namespace io = boost::iostreams;

int main() {
    std::stringstream ss;
    io::tee_device<decltype(ss), decltype(std::cerr)> sink(ss, std::cerr);
    io::stream<decltype(sink)> stream(sink);
    stream << "foo" << std::endl;
    std::cout << ss.str().length() << std::endl;
    return 0;
}

【讨论】:

    【解决方案4】:

    您需要继承streambuf 并将myErr 声明为使用您的子类的ostream。让输入函数什么都不做,然后将输出函数复制到您需要的任何流中。

    12 年前,我有一堂课做了类似的事情,但已经忘记了。我找不到一个很好的例子,但docs for streambuf 可能是一个起点。关注受保护的输出函数。

    【讨论】:

      【解决方案5】:

      您可以像这样创建myErr 类的类型:

      class stream_fork
      {
          std::ostream& _a;
          std::ostream& _b;
      
      public:
          stream_fork( std::ostream& a, std::ostream& b)
              :   _a( a ),
                  _b( b )
          {
          }
      
          template<typename T>
          stream_fork& operator<<( const T& obj )
          {
              _a << obj;
              _b << obj;
              return *this;
          }
      
          // This lets std::endl work, too!
          stream_fork& operator<<( std::ostream& manip_func( std::ostream& ) )
          {
              _a << manip_func;
              _b << manip_func;
              return *this;
          }
      };
      

      用法:

      stream_fork myErr( std::cerr, errorString );
      myErr << "Error Message" << std::endl;
      

      【讨论】:

      • 原谅我的天真,但是使用模板,这一切都必须在头文件中,是吗? (模板总是给我带来麻烦!)
      • 显然不是。幸运的是,这个解决方案不涉及提升(我不允许使用)。
      • 模板化操作符
      • 在以前遇到模板时,我最终会得到该函数的多个副本(每个 .o 文件都有自己的或其他的),但这似乎没有发生在这里!跨度>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 2020-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多