
On Tue, 15 Feb 2005 03:04:35 +0200 "Peter Dimov" <pdimov@mmltd.net> wrote:
struct Dummy { int a; }
class Lock { private: Dummy &_d; public: Lock( Dummy &d ) : _d(d) { std::cout << "Locked." << std::endl; } ~Lock( void ) { std::cout << "Unlocked." << std::endl; }
Dummy *operator->( void ) { return &_d; } };
class Ref { private: Dummy &_d; public: Ref( Dummy &d ) : _d(d) { }
Lock operator->(void) { return Lock(_d); } };
Your code is non-portable. You are assuming that the temporary Lock(_d) will be constructed directly in the return value, but this is not guaranteed.
I'm not sure I'm following "constructed directly in the return value"; but, it will be constructed before the call to Lock's Dummy *operator->( void ) as implied by x->a, below. Isn't this all that is required?
No, because ~Lock will be called twice.
Fair enough. I guess I was willing to overlook the absence of a copy ctor in Raz's pseudo-code that "does the right thing". The thing that I took away from the idea was the forced creation of a temporary that is scoped to the remaining duration of evaluation of the "full-expression" as presented in 12.2 of the standard. Yes, I did need to look it up :) ; as I was operating under the bogus belief that destruction of the temporary was a { ... } scoped thing and may be implementation dependent. Further, I'm used to following the { scoped_lock lk(mtx); ... } formula; making Raz's idea intriguing, at least. I guess the second paragraph of your initial reply gets at the point; is locking to "full-expression" scope useful? I can think of a danger: cout << x->a << long_running_overloaded_insertion_rhs;
From my read, the lock wouldn't be given up until after the second << gets evaluated. Does this make sense; or am I missing something else?