Boost logo

Boost :

From: Tom Widmer (tom_usenet_at_[hidden])
Date: 2006-08-09 12:48:29


Ñåðãåé Èëüèí wrote:
> Let’s add this code into the weak_ptr:
>
> shared_ptr<element_type> operator-> () const // throws bad_weak_ptr when expired
> {
> shared_ptr<element_type> temp = lock();
> if( !temp )
> boost::throw_exception( boost::bad_weak_ptr() );
> return temp;
> }
>
> New way of use weak_ptr:
> shared_ptr< MyClass > sp( new MyClass );
> weak_ptr< MyClass > wp(sp);
> try
> {
> wp->Use1();
> wp->Use2();
> }
> catch( const exception& e )
> {
> cout << e.what() << endl;
> }
>
> It seems to me, that my way is more convenient than old school:
>
> if(shared_ptr<MyClass> temp = wp.lock())
> {
> temp->Use1();
> temp->Use2();
> }
> else
> cout << "Cannot use, already destroyed" << endl ;

The two have different semantics - the first can execute Use1 but then
throw due to the pointee being destroyed before the call to Use2,
whereas the second version either calls both or neither. In addition,
this change encourages poor code (such as your example), where multiple
shared_ptrs are created unnecessarily, and exceptions can occur at
arbitrary points in a sequence of calls. Finally, a weak_ptr not being
available isn't really an exceptional circumstance, and if you really
want to avoid the if, you can write something like:

template <class T>
shared_ptr<T> throw_lock(weak_ptr<T> const& p)
{
   shared_ptr<T> temp(p);
   if(!temp)
     boost::throw_exception(boost::bad_weak_ptr());
   return temp;
}

then do:
throw_lock(wp)->Use1();
throw_lock(wp)->Use2();

At least the problems are explicit in that version.

All that said, operator-> might be a useful convenience for the case
where you are making only a single call, or you don't care about
exceptions or efficiency, but the problem is that people may start to
use it in all cases.

Tom


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk