Re: Order of evaluation of expression
"Ulrich Eckhardt" wrote:
In other words, your design will work correctly. However, there is one thing
there which I don't like, and that is the fact that it slightly obfuscates
what is going on. Consider these alternatives:
1. Use the comma operator:
Latch(lck), std::wcout << L"Fou" << L"Barre!" << std::endl;
This has the same guarantees, only that the Latch will be created before the
right side of the comma is evaluated.
I use precisely this when I do other operations requiring the same lock
(changing the file or output buffer). However, with the code as written I am
looking for ways to leave it as close to the existing syntax as possible, so
I will probably go for what described in my reply to Doug (illustrated by
wlog() function).
2. Use a wrapper around the stream:
MyLatch(std::wcout) << L"Fou" << L"Barre!" << std::endl;
The MyLatch would have a templated, overloaded operator<< which then returns
just the stream.
Note that if you want a prefix at the beginning of a line, you might need
something like this:
struct wrapper: std::wostringstream {
wrapper(std::wostream& target): m_target(target) {}
~wrapper() {
std::wstring const& s = this->str();
// chop into lines and forward to m_target
}
private:
std::wostream& m_target;
};
This can also keep the locking time of the target stream a bit lower,
because you only feed it complete lines at a time instead of formatting the
output while the stream is already locked. You will have to copy the format
flags though, if that is important.
This is exactly how it is at the moment and locking happens precisely in the
destructor when all output is ready, which does seem to improve things quite
a bit. However, to make output look like this:
log() << "Output 1\n" << "Output 2\n";
I only managed this:
inline std::basic_ostream<_TCHAR>& log(const Log& lg = Log())
{
return const_cast<Log&>(lg);
}
(where Log is an equivalent of your wrapper) and did not like it.
Anyway, thank you for your reply.