returns 一个ostream的C++函数

C++ function that returns an ostream

我有许多 operator<<() 功能都是从做类似的事情开始的,所以我想将其抽象化。这是我正在尝试做的事情的最小可重现案例(所有的复杂性都被去掉了)。请注意,它不会编译。如果它编译通过了,我希望程序自己在一行上打印数字 3。

/*                                                                                                   
  clang++ -std=c++14 -Wall -Wextra foo.cc -o foo                                                     
*/

#include <ostream>
#include <iostream>

using std::cout;
using std::endl;
using std::ostream;

ostream& BaseFunction(ostream& os, const int x) {
  return os << x;
}

int main(int argc, char *argv[]) {
  cout << BaseFunction(cout, 3) << endl;
}

错误是这样开始的:

foo.cc:17:8: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and
      'ostream')
  cout << BaseFunction(cout, 3) << endl;
  ~~~~ ^  ~~~~~~~~~~~~~~~~~~~~~

然后提供大量“未知从 ostream 到 T 的转换”建议。

有人看到我做错了什么吗?

你可以试试这个:

BaseFunction(cout, 3);
cout << endl;

我认为 ostream 无法输出 ostream。

Basefunction(cout, 3) returns cout.

因此,最后一行相当于

cout << 3;
cout << cout << endl;

因为 cout << cout 没有意义,你得到一个错误。

你为此使用了一种非常奇怪和独特(即糟糕)的模式,使用它的方式是:

BaseFunction(cout, 3) << endl;

请注意,您将输入流作为参数传递给函数,并且由于您 return 将流作为输出,因此没有 operator<< 的重载在左侧和右侧同时使用,使用 C++ 流的常规方式在这里不起作用。

完成此操作的通常方法是添加一个 operator<< 重载,它接受一个 left-side 流和一个 right-side 自定义对象,它会执行您需要的任何操作来显示您的目的。在您的情况下,将函数替换为不将流作为参数的函数,并且 return 是一个自定义对象,然后您可以使用该对象来重载流运算符。

您所做的实际上是定义自定义流操纵器。可以更像这样实现:

/* clang++ -std=c++14 -Wall -Wextra foo.cc -o foo */

#include <iostream>
using std::cout;
using std::endl;
using std::ostream;

struct myValue {
    int value;
};

myValue BaseFunction(const int x) {
    return myValue{x};
}

ostream& operator<<(ostream &os, const myValue &v) {
    return os << v.value;
}

int main(int argc, char *argv[]) {
    cout << BaseFunction(3) << endl;
}

Live Demo