Johannes said:
Jonathan said:
Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}
Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.
You seem to want two things here: print timestamps on each line AND at
the end of each statement. The former is easy and the latter is not.
Yeha. The second one is my problem :/
For the statements, on top of my head, you could return a proxy from
the first operator<< and have that proxy set a flag in timestamp_out
when it is destroyed. Since this temporary will exist until the end of
the statement, it will probably work.
Hm, can u explain it to me with more detail? I'am not that fit in C++
When you do
out << "one" << "two";
you'll want the first operator to return a proxy.
timestamp_out_proxy operator<<(timestamp_out& out, const std::string&
s)
{
timestamp_out_proxy p(out);
p.print(s);
return p;
}
So
operator<<(out, "one")
will return the proxy. Next, you'll want to define an operator<< for
the
proxy.
timestamp_out_proxy& operator<<
(timestamp_out_proxy& p, const std::string& s)
{
p.print(s);
return p;
}
Your proxy is a way to do something before the first output and after
the
last output in a single statement. That is, with
timestamp_out out;
out << "one" << "two";
a proxy will get constructed for "one" and will be destroyed after
"two"
(at the end of the statement). So you can use the constructor and
destructor of the proxy.
class timestamp_out_proxy
{
public:
// This constructor is called when outputting "one". It stores the
// stream and you'll understand copy_ later.
//
timestamp_out_proxy(timestamp_out& out)
: out_(out),
copy_(false)
{
}
// This constructor is called when the proxy is returned from the
// operator<<. Note that we return it by value so a copy may be
created.
// That means the original proxy will get destroyed and you'll get
// additional timestamps printed. You want the action to take place
at
// the destruction of the last proxy on the statement so you have to
// track copy construction.
//
timestamp_out_proxy(timestamp_out_proxy& p)
: out_(p.out_),
copy_(false)
{
p.copy_ = true;
}
// You'll see newline_ and timestamp_ later.
//
~timestamp_out_proxy()
{
if (!copy_)
{
// when a proxy is destroyed (end of a statement), you want the
// next output to be on a new line with [TIMESTAMP]
//
out_.newline_ = true;
out_.timestamp_ = true;
}
}
// This only forwards to the stream.
//
void print(const std::string& s)
{
out_.print(s);
}
private:
timestamp_out& out_;
bool copy_;
};
Now, on with the actual stream.
class timestamp_out
{
friend timestamp_out_proxy;
public:
// A trick here. At the very first output, you want to print a
timestamp
// but no new line.
//
timestamp_out()
: newline_(false),
timestamp_(true)
{
}
// Prints the string with timestamps and newlines
//
void print(const std::string& s)
{
// A newline will be printed iif a proxy object was destroyed.
if (newline_)
std::cout << "\n";
// A timestamp will be printed if
// 1) the stream was just created (very first output)
// 2) a proxy object was destroyed
if (timestamp_)
std::cout << "[TIMESTAMP] ";
// All subsequent strings will be printed as is (unless they have
// newlines in them).
newline_ = false;
timestamp_ = false;
// This will replace
// "Hi.\nI'm a"
// with
// "Hi.\n[TIMESTAMP} I'm a"
std::cout << boost::replace_all_copy(s, "\n", "\n[TIMESTAMP] ");
}
private:
// these control the *next* output
bool newline_;
bool timestamp_;
};
And finally:
int main()
{
timestamp_out out;
out << "Hi.\nI'am a" << " Computer.";
out << "Nice.";
}
Jonathan