Re: Order of evaluation of expression
Paul wrote:
I am thinking of implementing a manipulator for a stream whose role would
be to lock the stream, run some prefix code (output a few initial values)
and then run some suffix code (flush and unlock the stream).
Okay.
struct Lock {
void lock();
void unlock();
};
struct Latch {
Latch(Lock& lck) : lock(lck) { lock.lock(); }
~Latch() { lock.unlock(); }
private:
Lock& lock;
};
inline std::wostream& operator <<(std::wostream& os, const Latch&)
{
return os;
}
int main()
{
Lock lck;
std::wcout << Latch(lck) << L"Something else 1.\n"
<< L"Something else 2.\n";
return 0;
}
The code seems to be working all right. Is there nothing wrong with this
idea?
I can't see anything why this shouldn't work.
My way of thinking is this. The arguments for the call to the << operator
will be created before the call. The order of creation is unspecified but
this does not matter - it is the output itself that does.
The Latch object will be created before any call to operator<< takes place
(because it is an argument), otherwise its creation time is unspecified. It
will be destroyed after the last call to operator<< because only there is a
sequence point where temporaries are destroyed.
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.
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.
Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite
Sator Laser GmbH
Gesch??ftsf??hrer: Thorsten F??cking, Amtsgericht Hamburg HR B62 932