在实际应用中,有时候需要对流的输出格式进行设定。比如说,需要对文件流中内置类型之间加上分隔符。而在输出到终端则加上空格。对文件流则有其他的格式要求。为每一种流都定义一个格式的输出太麻烦,而且对已经封装好的类则不可以去内部修改它们的输出操作符。因此,我们需要定义一个包装过的流类型,它通过模板参数接受一个内置的流,然后对不同的内置类型执行相应的输出操作。
(1)
为了方便起见,我们还需要对std::endl进行重载,它的类型是std::ostream&(*)(std::ostream&)。
(2)
这样,只要任何一个类重载了模板类型的输出操作符,那么就可以利用我们自己定义的类代替cout.
(3)
:最后要设置一下状态变量,因为第一个输出是不应该换行的。
#include "iostream"
#include "string"
#include "sstream"
#include "vector"
#include "cmath"
#include "algorithm"
#include "numeric"
template <typename OutputStream>
class myos{
public:
myos(OutputStream& os = std::cout) :os_(os),first_(true){}
myos& operator<<(int val){ prefix(); os_ << val; return *this; }
myos& operator<<(std::string val){ prefix(); os_ << val; if (val == "\n"){ os_<< "f"; }return *this; }
myos& operator<<(std::ostream&(*f)(std::ostream&))
{
os_<< f;
if (f == std::endl)
first_ = true;
return *this;
}
private:
OutputStream& os_;
bool first_;
void prefix(){
if (first_)
first_ = false;
else
os_ << '\t';
}
};
class Test{
int a = 0;
std::string b = "fuck";
template<typename T>
friend T& operator << (T& os, Test& t);
};
template<typename T>
T& operator << (T& os, Test& t)
{
os << t.a << t.b;
return os;
}
int main()
{
auto w = myos<std::ostream>();
auto t = Test();
w<< t <<std::endl<<'a';
std::cout << std::endl;
return 0;
}