Boost logo

Boost :

Subject: Re: [boost] [Boost.Breakable] Any interest in a Boost Breakable library?
From: OvermindDL1 (overminddl1_at_[hidden])
Date: 2009-09-07 04:44:26


On Mon, Sep 7, 2009 at 1:40 AM, Gottlob Frege<gottlobfrege_at_[hidden]> wrote:
> On Mon, Sep 7, 2009 at 2:14 AM, Pierre
> Morcello<pmorcell-cppfrance_at_[hidden]> wrote:
>> Thanks Michael, I did not think sooner to the 'else if'. But there is one problem with the 'else if' : you can not do calculations between the tests.
>>
>> When I work often my code looks like :
> ...
>
> Another 'lifer' here (20+ years!) :-)
>
> I think, by now, we all know and have seen the type of code you are
> talking about.  I saw it a lot with Windows GUI programming - get the
> HWND, check, Get the DC, check, do some stuff, make a HPEN, check,...
>
> I have yet to see a perfect solution.  Some of the solutions I've seen:
>
> 1) try to do all the checks at the top:
>
> void func(P1 p1, P2 p2, ...)
> {
>   if (!IsOK(p1)) return;
>   if (!IsOK(p2)) return;
>   etc
>
>   now do stuff...
> }
>
> I think this is pretty good if all the checks are just checking
> inputs.  but it gets hairy in those cases, as mentioned, when there is
> other code in between.  An alternative to this is to
>
> 2) do checks, then pass it down to unchecked functions:
> void func(P1 p1, P2 p2, ...)
> {
>   if (!IsOK(p1)) return;
>   if (!IsOK(p2)) return;
>
>   return unchecked_func(p1, p2, ...);
> }
>
> This actually CAN (somewhat) work with code in between - after every
> single check you call another smaller function.  But you end up with a
> cascade of functions (hard to follow) and you quickly run out of good
> names or reuse the same name if the param types have changed.  But it
> can also be helpful if the inner functions can be reused in cases
> where you, say, already had a DC or HPEN or something. ie
>
> void func(P1 p1, P2 p2, ...)
> {
>   Q q = getQ(p1);
>   if (!IsOK(q)) return;
>   return foo(q, p2,...);  // then foo(Q,...) then assumes Q, handles
> p2, maybe calls down another layer.
> }
>
>
> 3) use gotos
> Maybe gotos are evil, but I've seen 'goto cleanup' or 'goto
> endoffunction' and it doesn't really bother me that much.  It is sort
> of a poor man's 'finally' construct. As long as you are not going to
> multiple labels, or going back to the top (ie only 'goto' to labels
> closer to the end of the function) I can live with it.
>
>
> 4) mulitple returns strewn about
> I think there are a few reasons to avoid multiple returns, but a few
> of them need revisiting.  In particular, one reason was that multiple
> returns tended to cause resources to go un-destructed.  At least in
> the C days.  But now, if we are coding to be exception safe, then
> basically we are dealing with multiple return points whether we want
> to or not.  ie if an exception happens in the middle of the function,
> then that's where we are 'returning' from.  Or at least realize that
> if everything is RAII and exception safe, then the code is also
> 'return safe'.
> Multiple return points might still be harder to read and reason with
> (although not much different than multiple breaks), but at least it
> should now be 'safe'.
> P.S. multiple returns were once hard to debug, (you had to put
> breakpoints at every return if you didn't want to miss your exit) but
> now you can typically put a breakpoint at the closing '}' of the
> function itself, and catch them all (although you still might not know
> which one it was).
>
> 5) exceptions
> I've tried throwing exceptions, but found a few things
> a) some of the errors were not 'exceptional'
> b) it felt odd (to me) to catch exceptions thrown within the same
> function (as opposed to catching exceptions thrown from lower levels)
> c) it didn't look like less code than other solutions
> Of course, there are cases where the errors SHOULD be thrown up to a
> higher level, and that does make the code cleaner (particularly if
> there is NO catching in the current function) so it would make sense
> to use it in those situations.
>
> 6) Your 'Breakable' idiom
> Well, I haven't tried it.  I really dislike macros.  Probably that
> would be enough to stop me.  Not sure I like
>
>   for (bool executed=false;!executed;executed=true)
>
> any better.  I'd have to comment that, and then why not use a macro,
> which would be a comment at the same time.
>
> 7?)  Interestingly, I think I would be fine with it, if it was built
> into the language.  ie why not allow a break out of 'unnamed' blocks?
> (besides breaking some existing code with these blocks within loops,
> of course :-)
>
>    {
>         if (bad(x))
>            break;
>         y = ....;
>         if (!y)
>            break;
>    }
>
> I think I recall proposals for 'named'  breaks, and multilevel breaks as well?
>
>
> Anyhow, I think that is a long way for me to just say "I feel your
> pain", and I wish there was a nicer solution (that was part of the
> language).  I might even try your style.  If I DID start using it
> regularly, I'd definitely want it to be in boost, even if it was tiny
> - because then it would become a known and understood idiom.  But I'd
> prefer better language support instead.

Actually the D language has such named blocks and jumps to parent
loops from child ones and so forth, might look at it as an example...


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