F. *_*mir 2 c++ operator-overloading c++11
我有一个C++类,我在其中放置了许多std :: cout语句来打印有关此类正在处理的大量信号的信息性文本消息.我的目的是将这些文本消息重定向到名为log的函数.在这个函数中,我有一个名为mVerbose的标志,它定义是否应该打印日志文本.该功能的内容如下:
void XXXProxy::log(std::stringstream& ss)
{
if(mVerbose)
{
std::cout << ss;
ss << "";
}
}
Run Code Online (Sandbox Code Playgroud)
然后,此函数的调用者代码片段如下:std :: stringstream logStr;
logStr << "SE"
<< getAddr().toString()
<< ": WAITING on epoll..."
<< std::endl;
log(logStr);
Run Code Online (Sandbox Code Playgroud)
我想以一种我可以摆脱创建std :: stringstream对象并调用日志函数的方式重载我的XXXProxy中的<<运算符.我希望能够如下记录文本消息,让<<运算符将所有内容汇总到:
<< "SE"
<< getAddr().toString()
<< ": WAITING on epoll..."
<< std::endl;
Run Code Online (Sandbox Code Playgroud)
所以我希望有一个成员<<功能看起来像:
void XXXProxy::operator << (std::stringstream& ss)
{
if(mVerbose)
{
std::cout << ss;
ss << "";
}
}
Run Code Online (Sandbox Code Playgroud)
题
我是一个相对新手的C++开发人员,在编写上述类似<<运算符的句子时,会遇到很多编译错误.您能否提出一些建议或指导我一些链接让我正确实现这个<<运算符.谢谢.
如果你不想std::cout直接使用,你想拥有自己的Log类,你可以实现一个简单的包装器,提供相同的接口std::ostream:operator <<:
class Log {
private:
std::ostream& _out_stream;
//Constructor: User provides custom output stream, or uses default (std::cout).
public: Log(std::ostream& stream = std::cout): _out_stream(stream) {}
//Implicit conversion to std::ostream
operator std::ostream() {
return _out_stream;
}
//Templated operator>> that uses the std::ostream: Everything that has defined
//an operator<< for the std::ostream (Everithing "printable" with std::cout
//and its colleages) can use this function.
template<typename T>
Log& operator<< (const T& data)
{
_out_stream << data;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果您std::ostream& operator>>(std::ostream& os , const YourClass& object)为类实现,则可以使用此Log类.
这种方法的优点是您使用相同的机制来完成std::cout << your_class_object工作,并使类与Log一起工作.
struct Foo
{
int x = 0; //You marked your question as C++11, so in class initializers
//are allowed.
//std::ostream::operator<< overload for Foo:
friend std::ostream& operator<<(std::ostream& os , const Foo& foo)
{
os << foo.x;
}
};
int main()
{
Log my_log;
Foo my_foo;
my_foo.x = 31415;
my_log << my_foo << std::endl; //This prints "31415" using std::cout.
}
Run Code Online (Sandbox Code Playgroud)
extern const类Log,并使该类实现单例.这允许访问程序中的所有日志.Log output (17:57): log message.要做到这一点,你可以std::endl用作哨兵; 并存储一个标志,表示下一个输出是一行的开头(日志消息的开头).Ckeckout 下一个答案的完整和工作落实.示例的时间戳只是一个例子:).
但如果你喜欢,我们可以尝试实现它.值得庆幸的是C++ 11及其STL的重大改进,我们有一个很好的时间/日期API:std :: chrono
std::chrono基于三个方面:
另外,计时提供了三种类型的时钟,std::system_clock,std::steady_clock,和std::high_resolution_clock.在我们的例子中,我们使用std::system_clock(我们希望访问日期时间,而不是确定精确的时间间隔).
有关std :: chrono的更多信息,请查看这个很棒的Bo Qian的youtube教程.
因此,如果我们必须为日志头实现时间戳,我们可以这样做:
编辑:像其他好东西一样,C++模板是很好的工具,直到你过度使用它.
我们的问题是这std::endl是一个模板化的函数,所以我们不能将它直接传递给另一个模板化的参数(operator<<在我们的例子中),因为编译器不能直接推导出std :: endl模板的规则.这是重复错误"未解决的重载函数类型".
但有一个更简单的方法来做到这一点:使用一个明确的过载operator<<为std::endl唯一的,和其他模板的一切:
class Log
{
private:
std::ostream& _out_stream;
bool _next_is_begin;
const std::string _log_header;
using endl_type = decltype( std::endl ); //This is the key: std::endl is a template function, and this is the signature of that function (For std::ostream).
public:
static const std::string default_log_header;
//Constructor: User passes a custom log header and output stream, or uses defaults.
Log(const std::string& log_header = default_log_header , std::ostream& out_stream = std::cout) : _log_header( log_header ) , _out_stream( out_stream ) , _next_is_begin( true ) {}
//Overload for std::endl only:
Log& operator<<(endl_type endl)
{
_next_is_begin = true;
_out_stream << endl;
return *this;
}
//Overload for anything else:
template<typename T>
Log& operator<< (const T& data)
{
auto now = std::chrono::system_clock::now();
auto now_time_t = std::chrono::system_clock::to_time_t( now ); //Uhhg, C APIs...
auto now_tm = std::localtime( &now_time_t ); //More uhhg, C style...
if( _next_is_begin )
_out_stream << _log_header << "(" << now_tm->tm_hour << ":" << now_tm->tm_min << ":" << now_tm->tm_sec << "): " << data;
else
_out_stream << data;
_next_is_begin = false;
return *this;
}
};
const std::string Log::default_log_header = "Log entry";
Run Code Online (Sandbox Code Playgroud)
此代码段完美无缺.我已将完整的实现推送到我的github帐户.
| 归档时间: |
|
| 查看次数: |
5973 次 |
| 最近记录: |