0

我想将类实例的文本描述放到 ostream 上,如

ostream << myInstance;

我知道如何声明一个 ostream 插入器;

ostream& operator<<(ostream&, myClass&);

我希望能够将不同级别的细节放到 ostream 中。如果我可以定义两个或多个 ostream 插入器,或者向插入器传递一个额外的参数,或者向插入器传递一个方法,或者调用一个返回字符串流的方法,我就可以做到这一点(我可以这样做吗?)

有没有人解决过这个问题?

4

4 回答 4

2

您可以通过实际封装流本身来将“标志”添加到流中。

struct Verbose {
  explicit Verbose(std::ostream* s = 0): _stream(s) {}
  std::ostream* _stream;
};

Verbose operator<<(std::ostream& out, Verbose) {
  return Verbose(&out);
}

然后,为详细输出定义一个新的运算符:

std::ostream& operator<<(Verbose v, MyClass const& mc) {
  assert(v._stream);
  std::ostream& out = *v._stream;

  // ...
  return out;
}

用法:

std::cout << Verbose() << myInstance << "\n";

你会注意到它Verbose根本不依赖于类,并且可以很容易地在类中重用。

注意:如果你愿意,你可以添加一个额外的参数来Verbose直接控制详细程度。

于 2011-11-23T17:42:02.157 回答
2

标准的解决方案是定义一个自定义操纵器,使用存储在由ios::xalloc. 就像是:

int
flagIndex()
{
    static int const theIndex = std::ostream::xalloc();
    return theIndex;
}

std::ostream&
verbose( std::ostream& stream )
{
    stream.iword( flagIndex() ) = 1;
    return stream;
}

std::ostream&
unverbose( std::ostream& stream )
{
    stream.iword( flagIndex() ) = 0;
    return stream;
}

std::ostream&
operator<<( std::ostream& dest, MyClass const& object )
{
    bool verbose = dest.iword( flagIndex() ) != 0;
    //  ...
    return dest;
}

然后,您可以编写如下内容:

std::cerr << verbose << myObject;
于 2011-11-23T18:05:09.213 回答
1

您不能向 中添加额外的参数operator<<,但您可以轻松定义采用详细参数的自定义打印函数:

void dump(ostream& ostr, const myClass& obj, int verbosity = 1)
{
    if (verbosity > 2)
      ostr << "Very verbose!\n";
    if (verbosity > 1)
      ostr << "Verbose!\n";
    if (verbosity > 0)
      ostr << "Standard!\n";
    ostr << "Minimal.\n";
}

用法:

dump(cout, myobj);     // Default
dump(cout, myobj, 0);  // Minimal
dump(cout, myobj, 1);  // Default
dump(cout, myobj, 2);  // Verbose
dump(cout, myobj, 3);  // Very verbose

您还应该提供一个流操作符转发到dump(),使用默认的详细程度:

ostream& operator<<(ostream& ostr, const myClass& obj)
{
    dump(ostr, obj);
    return ostr;
}

如果您想遵循这种方式,最好enum为详细程度声明 an 而不是使用ints:

enum Verbosity
{
    MinimalOutput = 0,
    StandardOutput = 1,
    VerboseOutput = 2,
    DebugOutput = 3
};
于 2011-11-23T17:15:23.887 回答
0

修改项目格式的标准方法是实现操纵器。它通常只会设置一些标志。然后,您的插入器将根据标志的状态修改其行为。

于 2011-11-23T17:15:25.260 回答