So I use such Log class:
#include <stdio.h>
#include <iostream>
class Log
{
public开发者_如何学JAVA:
int i;
Log()
{
i = 0;
}
template <class T>
Log &operator<<(const T &v)
{
i++;
std::cout << i << ":" << v << ";" <<std::endl;
return *this;
}
Log &operator<<(std::ostream&(*f)(std::ostream&))
{
i++;
std::cout << i << ":" << *f << ";" <<std::endl;
return *this;
}
~Log()
{
std::cout << " [end of message]" << std::endl;
}
};
Which I use like:
#include <log.h>
int main()
{
Log a;
a << "here's a message" << std::endl;
a << "here's one with a number: " << 5;
std::cin.get();
}
I want my log class to get when I put ";" meaning if I have a << "here's a message" << std::endl;
I want it to be capable to get that it is oune log message and a << "here's one with a number: " << 5;
is another.
crently it outputs next message:
1:here's a message;
2:
;
3:here's one with a number: ;
4:5;
I want to keep its sintax (unlimited number of <<
, big range of value types, no (
and )
around in api) but make it output:
1:here's a message
;
2:here's one with a number: 5;
How to do such thing?
Make operator<<
return a temporary value which will place endl
upon destruction and forwards all operator<<
calls to the main object. This way, endl
is guaranteed to be called exactly once.
class Log
{
struct EndlOnDeath {
Log* log;
EndlOnDeath(Log* ptr)
: log(ptr) {}
template<typename T> EndlOnDeath& operator<<(const T& val) {
(*log) << val;
}
~EndlOnDeath() {
(*log) << std::endl;
}
};
public:
int i;
Log()
{
i = 0;
}
template <class T>
EndlOnDeath operator<<(const T &v)
{
i++;
std::cout << i << ":" << v << ";";
return this;
}
Log &operator<<(std::ostream&(*f)(std::ostream&))
{
i++;
std::cout << i << ":" << *f << ";" <<std::endl;
return *this;
}
~Log()
{
std::cout << " [end of message]" << std::endl;
}
};
You can define a special object which, when inserted, indicates the end of the log entry. I know this is not exactly what you want, but it's really easy to implement. It also leaves you the flexibility to spread a log entry over several statements (which is useful for generating parts of a log entry within a loop, for example).
struct LogEnd {};
const LogEnd logend;
class Log
{
public:
Log() : number_(0) {}
template <typename T> Log& operator<<(const T& x)
{
ss_ << x;
}
Log& operator<<(const LogEnd& aLogEnd)
{
// Dump the stringstream string to output with desired decorations.
std::cout << number_ << ": " << ss_.str() << std::endl;
// Clear the stringstream
ss_.str("");
++number_;
}
private:
std::ostringstream ss_;
int number_;
};
int main()
{
Log log;
log << "This is " << 1 << " log entry" << logend;
}
精彩评论