Boost logo

Boost :

From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2002-09-28 10:43:21


David Abrahams wrote:
[...]
> I don't really like scopeguard-like things for such jobs, since the danger
> of the above is that you have to remember to throw;, while you need to
> remember to cancel the scopeguard.

Yep. bool hypothetical_std::unwinding<T>(T*) would solve this, I guess.
Another approach might be something like:

http://groups.google.com/groups?selm=3D89CACB.12BB6122%40web.de
(Subject: Re: C++0x: Proposal for an additonal exception handling construct)

---
template< class _FwdIt >
class _Uninit_fill_cleanup {
  _FwdIt const& m_First;
  _FwdIt const& m_Last;
  _FwdIt        m_Next;
public:
  _Uninit_fill_cleanup( _FwdIt const& _First, _FwdIt const& _Last ) :
     m_First( _First ),  m_Last( _Last ), m_Next( _First ) {
  }
 ~_Uninit_fill_cleanup() {
     if ( m_First != m_Last ) // if ( std::unwinding(this) ) // exceptional path
       for (; m_First != m_Next; ++m_Next)
         _Destroy(&*m_Next);
  } 
}; 
template< class _FwdIt, class _Tval > 
inline void _Uninit_fill( _FwdIt _First, _FwdIt _Last, const _Tval& _Val ) {
  _Uninit_fill_cleanup< _FwdIt > _Cleanup( _First, _Last );
  for (; _First != _Last; ++_First)
    _Construct(&*_First, _Val);
}
---
> It's an even trade. 
Nope. An "even trade" isn't
catch(...) {
  // Blah blah ...
  throw;
}
but rather (well, "almost" -- unwinding aside):
catch(...) {
  try {
    // Blah blah ...
  }
  catch(...) { std::terminate(); }
  throw;
}
> Of course if you factor in Mr. Terekhov's favorite issue 
> (weird entaglements with not-really-C++ platform "exceptions"), 
> the scopeguard might be a better solution.
And "action_on_propagation_of(<whatever>) {" might be even better, 
I guess.
http://groups.google.com/groups?selm=3D89CACB.12BB6122%40web.de
(Subject: Re: C++0x: Proposal for an additonal exception handling construct)
---
Well, I'll admit that I'll have no problems with something like
template<class _FwdIt,
class _Tval> inline
void _Uninit_fill(_FwdIt _First, _FwdIt _Last, const _Tval& _Val,
        _Nonscalar_ptr_iterator_tag)
{       // copy _Val throughout raw [_First, _Last), arbitrary type
  _FwdIt _Next = _First;
  try {
    for (; _First != _Last; ++_First)
      _Construct(&*_First, _Val);
  }
  action_on_propagation_of(...) {  /* THIS DOESN'T CATCH *UNEXPECTED* EXCEPTIONS */
                                   /* THIS DOES RETHROW EXCEPTIONS AUTOMATICALLY */
                                   /* NOTHING ELSE CAN BE THROWN FROM THIS SCOPE */
    for (; _Next != _First; ++_Next)
      _Destroy(&*_Next);
  }
}
---
David Abrahams also wrote: <another article>
[...]
> > especially if you are trying to
> > write safe portable code (besides, they could be implemented as
> "really-C++"
> > exceptions on a given platform too).
> 
> In that case, try/catch would be fine.
Nope. You wouldn't really want to ALWAYS have {partial} unwinding on 
std::logic_error (unless you *really really* want it for some reason 
that is beyond my understanding and/or imagination), would you? ;-)
Frankly, do YOU *also* kinda "doesn't seem to care"(*) with respect 
to thread cancel/exit safety of your code (given that sort of "brain-
dead" *forced unwinding* IS adopted by many many C++ vendors/platforms 
presently)? What am I missing, Mr. Abrahams?
regards,
alexander.
(*) http://groups.google.com/groups?threadm=3D8EEE36.C164536D%40web.de
    ("Subject: "PJP doesn't seem to care" ;-)" )

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