如何将上下文信息传递给自定义运算符<<适用于 std::iostream



我有一个大量使用(和优化)的类型,它通过使用小整数存储对更多数据的引用。对于调试,我想编写一个operator<<,用于访问其他数据以创建更好的调试输出。如何将这些额外的上下文信息传递给operator<<

下面是一个示例:

/** Rich information */
struct Item {
  short id;
  std::string name;
  ...
};    
struct Database {
  std::map<short,Item> items;
  ...
};
/** Very optimized light-weight data type */
struct Foo {
  short a, b; // actually references to Item
};
/** for debugging etc. */
void print(std::ostream& os, const Foo& f, const Database& db) {
  os << "(" << db.items[f.a].name << "," << db.items[f.b].name << ")";
}
Database db;
items[0] = {0, "item0"};
items[1] = {1, "item1"};
Foo foo{0,1};
std::cout << "foo="; print(std::cout, foo, db); std::cout << std::endl; // ugly
std::cout << "foo=" << foo << std::endl; // How to get db ???

您可以创建自己的操纵器print_database该操纵器重载operator <<

class print_database
{
public:
    print_database(const Foo& foo, const Database& db)
        : foo(foo), db(db)
    { }
    template<class cT>
    friend std::basic_ostream<cT>& operator<<(std::basic_ostream<cT>& os,
                                              const print_database& manip)
    {
        manip.print(os);
        return os;
    }
private:
    Foo foo;
    Database db;
    template<class cT>
    void print(std::basic_ostream<cT>& os) const
    {
        os << "(" << db.items[foo.a].name << "," << db.items[foo.b].name << ")";
    }
};

然后,您的print函数可以实现为:

print_database print(const Foo& foo, const Database& db)
{
    return print_database(foo, db);
}

所以现在你可以把它称为:

std::cout << print(foo, db) << std::endl;
我不知道

你是否认为它或多或少丑陋,但也许是这样的:

debug_printer dp { db };
std::cout << dp(foo) << std::endl;

调试打印机的op<<过载;或者op()可能会返回std::string

最新更新