如何为 cout 编写一个允许表达性语法的函数包装器?

mch*_*hen 5 c++ cout wrapper

我想包装std::cout格式,如下所示:

mycout([what type?] x, [optional args]) {
    ... // do some formatting on x first
    std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)

并且仍然能够使用表达性语法,例如

mycout("test" << i << endl << somevar, indent)
Run Code Online (Sandbox Code Playgroud)

而不是被迫像

mycout(std::stringstream("test") << i ...)
Run Code Online (Sandbox Code Playgroud)

我该如何实施?制作什么类型x

编辑:增加了对可选参数的考虑

0x4*_*2D2 5

使用可变参数模板参数可以很容易做到这一点:

template <class T>
void print(T t)
{
    std::cout << t;
}

template <class T, class... Args>
void print(T t, Args... args)
{
    std::cout << t << std::endl;
    print(args...);
}

int main()
{
    std::cout << std::boolalpha;
    print(3, 's', true, false);
}
Run Code Online (Sandbox Code Playgroud)

输出:

3
s
true
false

现场演示


Rei*_*ica 5

这个怎么样:

struct MyCout {};

extern MyCout myCout;

template <typename T>
MyCout& operator<< (MyCout &s, const T &x) {
  //format x as you please
  std::cout << x;
  return s;
}
Run Code Online (Sandbox Code Playgroud)

并放入MyCout myCout;任何一个 .cpp 文件中。

然后你可以myCout像这样使用:

myCout << "test" << x << std::endl;
Run Code Online (Sandbox Code Playgroud)

它会调用operator<<可以进行格式化的模板。

当然,如果需要,您还可以为特定类型的特殊格式提供运算符的重载。

编辑

显然(感谢@soon),要使标准操纵器正常工作,还需要更多的重载:

MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ostream &)) {
  f(std::cout);
  return s;
}

MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ios &)) {
  f(std::cout);
  return s;
}

MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ios_base &)) {
  f(std::cout);
  return s;
}
Run Code Online (Sandbox Code Playgroud)

编辑 2

我可能稍微误解了您最初的要求。这个怎么样(加上与上面相同的操纵器重载):

struct MyCout
{
  std::stringstream s;

  template <typename T>
  MyCout& operator << (const T &x) {
    s << x;
    return *this;
  }

  ~MyCout() {
    somehow_format(s);
    std::cout << s.str();
  }
};

int main() {
  double y = 1.5;
  MyCout() << "test" << y;
}
Run Code Online (Sandbox Code Playgroud)

  • “`myCout &lt;&lt; ... &lt;&lt; std::endl;`” 将不起作用(在您的情况下),因为 `operator&lt;&lt;` 没有为 `endl` 函数重载。 (2认同)