我想制作一个可以像 一样使用的记录器std::cout
,但我想记录一些额外的数据,例如日期、时间、、,__LINE__
并且__func__
应该__FILE__
自动保存到文件中。
例子
ToolLogger log;
log << "some data" << std::endl;
预期产出
[14.11.2015 21:10:12.344 (main.cpp) (main,14): some data
解决方案不足
为此,我必须将诸如__LINE__
直接之类的宏放在我调用记录器的行中,否则宏将无法正常工作。我发现我可以std::endl
用我的宏替换,它会像这样执行这个黑魔法:
#define __FILENAME__ (strrchr(__FILE__,'/') ? strrchr(__FILE__,'/') + 1 : __FILE__)
#define logendl \
((ToolLogger::fileName = __FILENAME__).empty() ? "" : "") \
<< ((ToolLogger::line = __LINE__) ? "" : "") \
<< ((ToolLogger::function = __func__).empty() ? "" : "") \
<< std::endl
该宏logendl
使用我的ToolLogger
类中的静态变量来保存 的值__LINE__
,__func__
并在__FILE__
以后需要。所以实际使用记录器将如下所示:
ToolLogger log;
log << "some data" << logendl;
在课堂上,我必须重载operator<<
才能让它工作,我需要其中两个。一个用于取正常值,如std::string
or int
,另一个用于取std::endl
操纵器。这是我班上最重要的事情:
class ToolLogger
{
public:
// standard operator<< //
template<typename T>
ToolLogger& operator<< (const T& str)
{
out << str;
return *this;
}
// operator<< for taking the std::endl manipulator //
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
typedef CoutType& (*StandardEndLine)(CoutType&);
ToolLogger& operator<<(StandardEndLine manip)
{
// save fileName, line and function to the file //
// and all what is already in stringstream //
// clear stringstream //
return *this;
}
static string fileName;
static int line;
static string function;
private:
ofstream file;
std::stringstream out;
};
string ToolLogger::fileName;
int ToolLogger::line;
string ToolLogger::function;
问题
这个解决方案的问题是我可以通过两种方式使用我的记录器:
log << "some data" << logendl; // correct //
log << "some data" << std::endl; // compiles -> wrong /
所以实际上我需要operator<<
从我的类中删除带有std::endl
机械手的类,并以其他方式解决它,但该怎么做呢?我正在考虑将宏更改std::endl
为logendl
其他自定义操纵器,然后这个自定义操纵器将完成实际正在执行的工作operator<<
,但我不知道该怎么做。我正在寻找其他解决方案,有什么建议吗?