c++ - 在带有前缀的C++ 中,重载运算符 <<

  显示原文与译文双语对照的内容

我正在使用 C++ 中的记录器类,它具有以下语法:


Logger log("mylog.txt");


log <<"a string" <<"" <<1 <<"" <<6.2 <<"n";



它的指纹是 1 6.2

这就是我的类的外观:


class Logger 


{


private:


 unique_ptr<ofstream> m_pOutStream;



public: 


 Logger(std::string sFile) : m_pOutStream(new ofstream(sFile, std::ios::app))


 {}



 template<typename T>


 Logger& operator <<(const T& data)


 {


 *m_pOutStream <<data;


 return *this;


 }


};



它工作正常,但我也想为每一行添加一个前缀( 比如 。 时间戳) 。所以当我写的时候:


Logger log("mylog.txt");


log <<"a string" <<"" <<1 <<"" <<6.2 <<"n";



我希望显示如下内容:


11:59:12 a string 1 6.2



我已经考虑了几个解决方案:

1.Keep 存储在列表/流中的每个输入,并使用额外的函数打印,然后清除列表/流:


Logger log("mylog.txt");


log <<"a string" <<"" <<1 <<"" <<6.2 <<"n";


log.logd();//<- this prints and then clears the internal stream/list.



2.Keep 每个输入存储在列表/流中,并在检测到"新行"字符后打印所有内容。 然后清除内部流/列表之后。

这两个解决方案都不错,但我更愿意将它们作为最后的手段使用。

还有其他的方法来达到我想要的效果?

时间: 原作者:

std::stringbuf 派生一个类,比如 LoggerStringBuf,并在它的构造函数中给出对输出 std::ofstream的引用。 重写虚拟 std::stringbuf::sync() 方法从基 std::stringbuf::str() 方法检索 std::string,并在将它的写入到 std::ofstream 时使用时间戳前缀。 这样,每当 LoggerStringBuf 对象被刷新为 std::ofstream 时,就会生成一个新的时间戳,无论是 std::endl 还是 std::flush

然后让 Logger 类从 std::ostream 派生并使用 LoggerStringBuf 对象初始化它。 然后你可以将输入值流到 Logger,它们将被缓存到 LoggerStringBuf 对象中,直到刷新到 std::ofstream 。 在此时,你可以根据需要调整时间戳。

例如:


class LoggerStringBuf : public std::stringbuf


{


private:


 std::ostream &m_OutStream;



protected:


 virtual int sync()


 {


 int ret = std::stringbuf::sync();



 std::string s = str();


 str("");



//note sure if the string includes non-flushing


//line breaks. If needed, you can use std::getline()


//to break up the string into multiple lines and 


//write a timestamp for each line...


//


 m_OutStream <<"[timestamp]" <<s <<std::endl;



 return ret;


 };



public:


 LoggerStringBuf(std::ostream &OutStream)


 : std::stringbuf(std::ios_base::out), m_OutStream(OutStream)


 {


 }



 ~LoggerStringBuf()


 {


 sync();


 }


};



class Logger : public std::ostream


{


private:


 std::ofstream m_OutStream;


 LoggerStringBuf m_Buf;



public: 


 Logger(const std::string &sFile)


 : std::ostream(0), m_OutStream(sFile, std::ios::app), m_Buf(m_OutStream)


 {


 init(&m_Buf);


 }



 template<typename T>


 std::ostream& operator <<(const T& data)


 {


 return static_cast<std::ostream&>(*this) <<data;


 }


};



原作者:
...