Topic: Why is Duff's Device allowed?
Author: kanze@gabi-soft.de
Date: 2000/10/08 Raw View
llewelly.@@edevnull.dot.com writes:
|> David R Tribble <david@tribble.com> writes:
|> [snip]
|> > It all stems from the fact that 'case' is a statement label, akin t=
o
|> > goto labels, and not a flow control keyword proper. If it was the
|> > latter, then fall-through between case statements would make much
|> > less sense. This is the legacy of C, one that Bjarne did not chang=
e
|> > for C++ (nor did Gosling for Java).
|> It is worth pointing out that Bjarne had an excellent reason *not* to
|> change the behavior of C switch statements - backwards
|> compatibility. For C++, I think this is/was more important than the
|> bugs caused by the current switch semantics.=20
In the case of C++, fully agreed. what's the excuse for Java:-)?
Seriously, another argument is the reduced frequency of switch
statements in OO code -- a large percentage of my switches in C were to
accomplish what I do with virtual functions in C++. (Technically, *all*
switches can be replaced by a properly initialized map of
int->functional object. Practically, that's a pretty heavy solution for
some particular problems.)
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: afnevrau@student.math.uwaterloo.ca (Adam Frank Nevraumont)
Date: 2000/10/09 Raw View
In article <39DCC979.D8923B4@sensor.com>, Ron Natalie <ron@sensor.com> wrote:
>
>
>David R Tribble wrote:
>>
>=
>>
>> We could propose extending the C/C++ syntax to make cases like the one
>> above clearer, to wit:
>>
>> for (;;)
>> {
>> switch (e)
>> {
>> case 'a':
>> ...
>> continue for; // [A]
>
>UGH. why don't you just use goto then? It's already possible to
>break structuring with break/continue, we don't need to make it worse.
How would using goto break structuring less than the modification to continue
displayed above?
One doesn't want to use goto because a goto can be a nearly arbitrary jump
in code position. The above use of continue and break at least ensures the
change in code position is somewhat structured.
goto is technically sufficient, doesn't mean it should be all that is
availiable for the above case.
>> Or C/C++ could adopt the Java syntax that allows break/continue
>> statements to specify an outer loop/switch label, to wit:
>>
>> loop:
>> for (;;)
>> {
>> switch (e)
>> {
>> case 'a':
>> ...
>> continue loop; // [X]
>> case 'b':
>> ...
>> break; // [Y] break switch
>> default:
>> break loop; // [Z]
>> }
>> }
>>
>
> for(;;) {
> switch(e)
> {
> case 'a':
> goto loop;
> }
>
> loop:;
> }
Inferior. A continue loop; statement is much less powerful, and a goto
command at that location provides too much power.
break label; and continue label; are 'forward'-only goto's, and they can only
goto scope ends. In other words, a much weaker and less dangrous tool.
--
Adam_Nevraumont at uwaterloo.ca The problem with the Big Blue Room is
'Nemo enim fere saltat sobris, the daily 8 hour reboots.
nisi forte insait.' -- Cicero
Hi. Im the signature immune system. Why dont you copy me into your .sig?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: David R Tribble <david@tribble.com>
Date: 2000/10/05 Raw View
"Daryle Walker" <dwalker07@snet.net.invalid> wrote
>> If we use "break" to stop the currently default fall-through, why
>> don't we use "continue" to force a fall-through?
Balog Pal wrote:
> Don't even think about that!
> We have just enough problems with the extremely stupid selection of a
> break keyword working for switch and loops.
>
> for(;;) {
> switch(a)
> {
> case 'a':
> continue;
> default:
> break; // oops, that would mean break the for!
> }
> }
>
> Now adding continue to that group also would be really bad.
We could propose extending the C/C++ syntax to make cases like the one
above clearer, to wit:
for (;;)
{
switch (e)
{
case 'a':
...
continue for; // [A]
case 'b':
...
break switch; // [B]
default:
break for; // [C]
}
}
Or C/C++ could adopt the Java syntax that allows break/continue
statements to specify an outer loop/switch label, to wit:
loop:
for (;;)
{
switch (e)
{
case 'a':
...
continue loop; // [X]
case 'b':
...
break; // [Y] break switch
default:
break loop; // [Z]
}
}
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Ron Natalie <ron@sensor.com>
Date: 2000/10/05 Raw View
David R Tribble wrote:
>
=
>
> We could propose extending the C/C++ syntax to make cases like the one
> above clearer, to wit:
>
> for (;;)
> {
> switch (e)
> {
> case 'a':
> ...
> continue for; // [A]
UGH. why don't you just use goto then? It's already possible to break structuring with
break/continue, we don't need to make it worse.
> Or C/C++ could adopt the Java syntax that allows break/continue
> statements to specify an outer loop/switch label, to wit:
>
> loop:
> for (;;)
> {
> switch (e)
> {
> case 'a':
> ...
> continue loop; // [X]
> case 'b':
> ...
> break; // [Y] break switch
> default:
> break loop; // [Z]
> }
> }
>
for(;;) {
switch(e)
{
case 'a':
goto loop;
}
loop:;
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: llewelly.@@edevnull.dot.com
Date: 2000/10/08 Raw View
Ron Natalie <ron@sensor.com> writes:
> David R Tribble wrote:
> >
> =
> >
> > We could propose extending the C/C++ syntax to make cases like the one
> > above clearer, to wit:
> >
> > for (;;)
> > {
> > switch (e)
> > {
> > case 'a':
> > ...
> > continue for; // [A]
>
> UGH. why don't you just use goto then? It's already possible to
> break structuring with
> break/continue, we don't need to make it worse.
>
>
> > Or C/C++ could adopt the Java syntax that allows break/continue
> > statements to specify an outer loop/switch label, to wit:
> >
> > loop:
> > for (;;)
> > {
> > switch (e)
> > {
> > case 'a':
> > ...
> > continue loop; // [X]
> > case 'b':
> > ...
> > break; // [Y] break switch
> > default:
> > break loop; // [Z]
> > }
> > }
> >
>
> for(;;) {
> switch(e)
> {
> case 'a':
> goto loop;
> }
>
> loop:;
> }
With labeled break/continue, there are (or should be) rules about
where the destination label can be; it must be at the top of a loop
that contains the break or continue. This has 3 advantages over goto:
(0) The destination is easier to find, as there are fewer places to
look for it in.
(1) The construct is less error-prone.
(2) The break or continue is guaranteed to exit the block, and (for
continue) will re-enter the block at the top. This means that
labeled break/continue have no weird corner cases when it comes
to constructors and destructors.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Balog Pal" <pasa@lib.hu>
Date: 2000/09/27 Raw View
"Daryle Walker" <dwalker07@snet.net.invalid> wrote in message
> If we use "break" to stop the currently default fall-through, why don't
> we use "continue" to force a fall-through?
Don't even think about that!
We have just enough problems with the extremely stupid selection of a break
keyword working for switch and loops.
for(;;) {
switch(a)
{
case 'a':
continue;
default:
break; // oops, that would mean break the for!
}
}
Now adding continue to that group also would be really bad.
Paul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: Tue, 26 Sep 2000 00:07:47 GMT Raw View
Daryle Walker wrote:
> If we use "break" to stop the currently default fall-through, why
> don't we use "continue" to force a fall-through? (We can still use
> "break" to force a case exit in the new system.) I can guess that
> making "continue" orthogonal with "break" with respect to "switch"es
> has a problem, it would change the behavior of a "continue" when it is
> in a "switch" surrounded by a loop.
It all stems from the fact that 'case' is a statement label, akin to
goto labels, and not a flow control keyword proper. If it was the
latter, then fall-through between case statements would make much
less sense. This is the legacy of C, one that Bjarne did not change
for C++ (nor did Gosling for Java).
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: llewelly.@@edevnull.dot.com
Date: 2000/09/27 Raw View
David R Tribble <david@tribble.com> writes:
[snip]
> It all stems from the fact that 'case' is a statement label, akin to
> goto labels, and not a flow control keyword proper. If it was the
> latter, then fall-through between case statements would make much
> less sense. This is the legacy of C, one that Bjarne did not change
> for C++ (nor did Gosling for Java).
It is worth pointing out that Bjarne had an excellent reason *not* to
change the behavior of C switch statements - backwards
compatibility. For C++, I think this is/was more important than the
bugs caused by the current switch semantics.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: dwalker07@snet.net.invalid (Daryle Walker)
Date: 2000/09/25 Raw View
<kanze@gabi-soft.de> wrote:
[SNIP]
> What might be useful would be to have a real switch statement that
> worked, with the cases requiring (or implicitly defining) separate
> blocks. This would avoid the surprise that occurs when one tries to
> declare a local variable with an initializer in one of the cases. This
> is also a much bigger modification -- it means *no* fall through, so you
> would also have to define a new way of specifying multiple cases.
If we use "break" to stop the currently default fall-through, why don't
we use "continue" to force a fall-through? (We can still use "break" to
force a case exit in the new system.) I can guess that making
"continue" orthogonal with "break" with respect to "switch"es has a
problem, it would change the behavior of a "continue" when it is in a
"switch" surrounded by a loop.
--
Daryle Walker
Mac, Internet, and Video Game Junkie
dwalker07 AT snet DOT net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/20 Raw View
In article <39C7B823.DDADDFFE@tribble.com>, David R Tribble
<david@tribble.com> writes
>> Sorry, but in all but the most extreme circumstances such code needs
>> immediate refactoring.
>
>"extreme cases" == "average C++ code".
NO.
"average C++ code" == "badly written, bug invested, almost
unmaintainable C++ code"
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Sean Kelly" <kensai@bellatlantic.net>
Date: 2000/09/20 Raw View
Here's the answer, from Tom Duff himself:
http://www.lysator.liu.se/c/duffs-device.html
Basically, this ingenious bit of code was developed because it produced the
most efficient block of machine code for the algorithm (at a time when CPU
cycles mattered). It's a very clever way to unwind a loop and still deal
properly with odd-sized arrays. The "why is it allowed" basically boils
down to the fact that the switch statement is a glorified goto block.
Sean
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 2000/09/18 Raw View
Phil McRevis <legalize+jeeves@xmission.com> writes:
>> I tend to favor switch if the body of my case statements are
>> relatively simple. Once my case bodies get complex with many of them
>> requiring local variables and many statements, I tend to favor an
>> if-else block. I think a case statement historically arises from the
>> "computed goto" or the jump table in assembly. You compute a value
>> and use the value as an index into a table of jump destinations.
>> The "break" constitutes the conscious decision to skip the remaining
>> instructions and jump to the end of the group of jump destinations.
>> This is very much the spirit of Duff's device, for instance, where
>> falling through to the succeeding case isn't a nuiscance, it's
>> essential to the idiom.
Francis Glassborow wrote:
> If it gets that complicated I prefer the code for such cases be
> encapsulated as a function.
That's great as long as the complicated case code doesn't have to
access many local variables within the containing function, or
cause the containing function to change flow control, such as
returning early.
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 2000/09/18 Raw View
dwalker07@snet.net.invalid (Daryle Walker) spake the secret code:
>> Reading a thread in comp.lang.c++.moderated, they talked about
>> something called Duff's Device:
>>
>> void send(int* to, int* from, int count)
>> {
>> int n = (count + 7) / 8;
>> switch (count%8) {
>> case 0: do { *to++ = *from++;
>> case 7: *to++ = *from++;
>> case 6: *to++ = *from++;
>> case 5: *to++ = *from++;
>> case 4: *to++ = *from++;
>> case 3: *to++ = *from++;
>> case 2: *to++ = *from++;
>> case 1: *to++ = *from++;
>> } while ( --n>0 );
>> }
>> }
Phil McRevis wrote:
> Looking at Duff's device again, I'm left with the feeling that 'case'
> is more like declaring a special kind of label and 'switch' is a
> special kind of 'goto', which is why case doesn't introduce a scope.
'switch'/'case' is indeed a special kind of goto; case and default
statements are lumped together with "labeled statements" in both C
and C++. Using the term "labeled" only makes sense if you're talking
about statements that are targets of goto or some other form of
jump transfer, i.e., switch.
> Consider rewriting Duff's device like this (this is only conceptual,
> it is not valid C code since constants can't be labels):
>
> goto count%8;
> 0: do {
> *to++ = *from++;
> 7: *to++ = *from++;
> 6: *to++ = *from++;
> 5: *to++ = *from++;
> 4: *to++ = *from++;
> 3: *to++ = *from++;
> 2: *to++ = *from++;
> 1: *to++ = *from++;
> } while (--n > 0);
>
> If you *could* write labels and use goto like that we wouldn't suffer
> the mental brain cramp of thinking that the labels had to introduce a
> scope. This is why I think of 'switch' as a form of computed goto
> like in FORTRAN.
Switch statements with a compound statement body do introduce a new
scope. But you must follow the rules about transferring control to
a point following the definition of auto/local variables. Consider
the following:
switch (count%8)
{
int n = foo(); // [A]
case 0: // [B]
...
case 1:
...
...
default:
...
}
Since the only way to transfer the flow of control into the compound
statement of the switch body is by a "goto" to one of the cases or
the default label (at [B] and beyond), this violates the rule about
transferring control to a point past the initialization of a local
variable (at [A]). Thus there seems to be no way to define local
variables within a switch body. Unless, of course, you don't
actually transfer control, as in this degenerate case:
switch (expr)
{
int n = foo();
// No case or default labels here
}
I'm not sure this is valid, though.
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/19 Raw View
In article <39C64C14.7CAB6540@tribble.com>, David R Tribble
<david@tribble.com> writes
>Francis Glassborow wrote:
>> If it gets that complicated I prefer the code for such cases be
>> encapsulated as a function.
>
>That's great as long as the complicated case code doesn't have to access
>many local variables within the containing function, or cause the
>containing function to change flow control, such as returning early.
>
Many local variables, flow control that interacts outside the controlled
block? We are talking about C++ aren't we? Sorry, but in all but the
most extreme circumstances such code needs immediate refactoring.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: <thp@roam-thp2.cs.ucr.edu>
Date: 2000/09/19 Raw View
kanze@gabi-soft.de wrote:
[...]
> Another particularity of the switch is that the labels don't have to
> be at the outer level. I remember once (a long time ago) writing
> something like:
> switch ( charCategory[ *p ] ) {
> case CH_DOT :
> if ( isdigit( *(p+1) ) ) {
> case CH_DIGIT :
> // process number token...
> } else {
> case CH_PUNCT :
> // process punctuation token...
> }
> break ;
> }
> (In the real program, of course, there were other cases as well.)
> This is also fully legal C/C++, but it is something that I wouldn't
> write today -- since then, I've worked on a number of really big
> projects, and have learned the importance of readable code.
It turns out that switch is sufficiently general that one can simulate
the indirect goto of gcc using a somewhat ugly switch-based hack. (I
need such things when I have students use low-level C instead of
assembly language as the output of their compiler projects.)
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 2000/09/19 Raw View
Francis Glassborow wrote:
>> If it gets that complicated I prefer the code for such cases be
>> encapsulated as a function.
David R Tribble <david@tribble.com> writes:
>> That's great as long as the complicated case code doesn't have to
>> access many local variables within the containing function, or cause
>> the containing function to change flow control, such as returning
>> early.
Francis Glassborow wrote:
> Many local variables, flow control that interacts outside the
> controlled block? We are talking about C++ aren't we?
Oh, I forgot that C++ forces programmers to code more thoughtfully.
(What if, for example, the case statement you wish to factor is nested
inside a complicated nested loop and modifies those loop control
variables?)
> Sorry, but in all but the most extreme circumstances such code needs
> immediate refactoring.
"extreme cases" == "average C++ code".
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Sun, 17 Sep 2000 04:35:58 GMT Raw View
Jonathan Biggar <jon@floorboard.com> writes:
|> I've found this pattern a useful example of Duff's Device:
|> enum { STATE_A, STATE_B, STATE_C, STATE_D } State;
|> void foo()
|> {
|> State s =3D STATE_A;
|> try {
|> // do work A
|> s =3D STATE_B;
|> // do work B
|> s =3D STATE_C;
|> // do work C
|> s =3D STATE_D;
|> // do work D;
|> }
|> catch (...) {
|> switch (s) {
|> case STATE_D:
|> // back out work C
|> case STATE_C:
|> // back out work B
|> case STATE_B:
|> // back out work A
|> case STATE_A:
|> // do nothing!
|> }
|> }
|> }
This isn't Duff's device. All you're doing is falling through in the
cases. What makes Duff's device special is that the statement in the
switch is not a compound statement, but a do statement. Another
particularity of the switch is that the labels don't have to be at the
outer level. I remember once (a long time ago) writing something like:
switch ( charCategory[ *p ] ) {
case CH_DOT :
if ( isdigit( *(p+1) ) ) {
case CH_DIGIT :
// process number token...
} else {
case CH_PUNCT :
// process punctuation token...
}
break ;
}
(In the real program, of course, there were other cases as well.)
This is also fully legal C/C++, but it is something that I wouldn't
write today -- since then, I've worked on a number of really big
projects, and have learned the importance of readable code.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Dietmar Kuehl <dietmar_kuehl@yahoo.com>
Date: 2000/09/15 Raw View
Hi,
In article <1egnw01.10m7wl01mb5czkN%dwalker07@snet.net.invalid>,
dwalker07@snet.net.invalid (Daryle Walker) wrote:
> Why is it allowed that a "case" statement doesn't have to be in the
> immediately-enclosing block of its "switch" statement? Is it just for
> C-compatibility (to perserve Duff's Device)? Doesn't this screw-up
> compiler parsing?
Personally, I think it is just the right thing to allow a 'switch'
statement to jump right where the programmer wants the switch to jump
to: I'm using this to implement algorithm objects where the user can
add actions at various points within the algorithm. The algorithm just
records the current state, returns, and branches to position where it
suspended itself for user interaction. Of course, I cannot declare
objects but this is non-issue because all objects are members of the
algorithm object for later resumption anyway. Also, fall through is
just the right thing...
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jonathan Biggar <jon@floorboard.com>
Date: 2000/09/15 Raw View
Daryle Walker wrote:
>
> Reading a thread in comp.lang.c++.moderated, they talked about something
> called Duff's Device:
I've found this pattern a useful example of Duff's Device:
enum { STATE_A, STATE_B, STATE_C, STATE_D } State;
void foo()
{
State s = STATE_A;
try {
// do work A
s = STATE_B;
// do work B
s = STATE_C;
// do work C
s = STATE_D;
// do work D;
}
catch (...) {
switch (s) {
case STATE_D:
// back out work C
case STATE_C:
// back out work B
case STATE_B:
// back out work A
case STATE_A:
// do nothing!
}
}
}
--
Jon Biggar
Floorboard Software
jon@floorboard.com
jon@biggar.org
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Tue, 12 Sep 2000 20:34:56 GMT Raw View
legalize+jeeves@xmission.com (Phil McRevis) writes:
|> kanze@gabi-soft.de spake the secret code
|> <86u2bo3tus.fsf@gabi-soft.de> thusly:
|> >[...] This would avoid the surprise that occurs when one tries to
|> >declare a local variable with an initializer in one of the cases.
|> What's wrong with introducing a local scope so you can declare the
|> variable for use in the case block? I do that when I want a local
|> variable that is only exposed for that particular case.
Most coding guidelines I see require just that. My own rule is exactly
what balog pal posted: the body of the case in braces, with the break
following. I do make a few exceptions, particularly for a default:
abort();. But basically, if you *always* need a new scope, why don't
you get one automatically? Or at least, why is the default to fall
through?
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: legalize+jeeves@xmission.com (Phil McRevis)
Date: 2000/09/13 Raw View
[Please do not mail me a copy of your followup]
kanze@gabi-soft.de spake the secret code
<867l8h4afx.fsf@gabi-soft.de> thusly:
>But basically, if you *always* need a new scope, why don't
>you get one automatically? Or at least, why is the default to fall
>through?
I tend to favor switch if the body of my case statements are
relatively simple. Once my case bodies get complex with many of them
requiring local variables and many statements, I tend to favor an
if-else block. I think a case statement historically arises from the
"computed goto" or the jump table in assembly. You compute a value
and use the value as an index into a table of jump destinations. The
"break" constitutes the conscious decision to skip the remaining
instructions and jump to the end of the group of jump destinations.
This is very much the spirit of Duff's device, for instance, where
falling through to the succeeding case isn't a nuiscance, its
essential to the idiom.
--
<http://www.xmission.com/~legalize/> Legalize Adulthood!
``Ain't it funny that they all fire the pistol,
at the wrong end of the race?''--PDBT
<http://www.xmission.com/~legalize/who/>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 2000/09/13 Raw View
In article <8poc2r$hi7$1@xmission.xmission.com>, Phil McRevis
<legalize+jeeves@xmission.com> writes
>I tend to favor switch if the body of my case statements are relatively
>simple. Once my case bodies get complex with many of them requiring
>local variables and many statements, I tend to favor an if-else block.
>I think a case statement historically arises from the "computed goto" or
>the jump table in assembly. You compute a value and use the value as an
>index into a table of jump destinations. The "break" constitutes the
>conscious decision to skip the remaining instructions and jump to the
>end of the group of jump destinations. This is very much the spirit of
>Duff's device, for instance, where falling through to the succeeding
>case isn't a nuiscance, its essential to the idiom.
If it gets that complicated I prefer the code for such cases be
encapsulated as a function.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: legalize+jeeves@xmission.com (Phil McRevis)
Date: 2000/09/14 Raw View
[Please do not mail me a copy of your followup]
dwalker07@snet.net.invalid (Daryle Walker) spake the secret code
<1egnw01.10m7wl01mb5czkN%dwalker07@snet.net.invalid> thusly:
>Reading a thread in comp.lang.c++.moderated, they talked about something
>called Duff's Device:
>
>//=====================================================
>void send(int* to, int* from, int count)
>{
> int n = (count + 7) / 8;
> switch (count%8) {
> case 0: do { *to++ = *from++;
> case 7: *to++ = *from++;
> case 6: *to++ = *from++;
> case 5: *to++ = *from++;
> case 4: *to++ = *from++;
> case 3: *to++ = *from++;
> case 2: *to++ = *from++;
> case 1: *to++ = *from++;
> }while ( --n>0 );
> }
>}
Looking at Duff's device again, I'm left with the feeling that 'case'
is more like declaring a special kind of label and 'switch' is a special
kind of 'goto', which is why case doesn't introduce a scope. Consider
rewriting Duff's device like this (this is only conceptual, it is not
valid C code since constants can't be labels):
goto count%8;
0:
do {
*to++ = *from++;
7:
*to++ = *from++;
6:
*to++ = *from++;
5:
*to++ = *from++;
4:
*to++ = *from++;
3:
*to++ = *from++;
2:
*to++ = *from++;
1:
*to++ = *from++;
} while (--n > 0);
If you *could* write labels and use goto like that we wouldn't suffer
the mental brain cramp of thinking that the labels had to introduce a
scope. This is why I think of 'switch' as a form of computed goto
like in FORTRAN.
--
<http://www.xmission.com/~legalize/> Legalize Adulthood!
``Ain't it funny that they all fire the pistol,
at the wrong end of the race?''--PDBT
<http://www.xmission.com/~legalize/who/>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: legalize+jeeves@xmission.com (Phil McRevis)
Date: Mon, 11 Sep 2000 18:26:24 GMT Raw View
[Please do not mail me a copy of your followup]
kanze@gabi-soft.de spake the secret code
<86u2bo3tus.fsf@gabi-soft.de> thusly:
>[...] This would avoid the surprise that occurs when one tries to
>declare a local variable with an initializer in one of the cases.
What's wrong with introducing a local scope so you can declare the
variable for use in the case block? I do that when I want a local
variable that is only exposed for that particular case.
--
<http://www.xmission.com/~legalize/> Legalize Adulthood!
``Ain't it funny that they all fire the pistol,
at the wrong end of the race?''--PDBT
<http://www.xmission.com/~legalize/who/>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: dwalker07@snet.net.invalid (Daryle Walker)
Date: Sun, 10 Sep 2000 16:14:07 GMT Raw View
Reading a thread in comp.lang.c++.moderated, they talked about something
called Duff's Device:
//=====================================================
void send(int* to, int* from, int count)
{
int n = (count + 7) / 8;
switch (count%8) {
case 0: do { *to++ = *from++;
case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
}while ( --n>0 );
}
}
//=====================================================
The placement of most of the "case" statements seems wierd. I thought
it should be interpreted as:
//=====================================================
void send(PARAMETERS)
{
INIT;
switch (SWITCH_TEST)
{
case 0:
do {
STATEMENTS
} while ( --n>0 );
}
}
//=====================================================
where the fact that the other "case" statements are enclosed in an inner
block should protect them from the switch. That could give a warning
about the other "case" statements (no owning "switch" statement). This
would be similar to having two "if" statements followed by an "else"
statement, the "else" statement would attach to the second "if"
statement, unless the second "if" statement is enclosed in a block
(probably by the first "if" statement). But the standard allows
indirect enclosement (C++ standard, section 6.4.2, paragraph 6, ending
sentence note)!
Why is it allowed that a "case" statement doesn't have to be in the
immediately-enclosing block of its "switch" statement? Is it just for
C-compatibility (to perserve Duff's Device)? Doesn't this screw-up
compiler parsing?
--
Daryle Walker
Mac, Internet, and Video Game Junkie
dwalker07 AT snet DOT net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kanze@gabi-soft.de
Date: Sun, 10 Sep 2000 20:20:28 GMT Raw View
dwalker07@snet.net.invalid (Daryle Walker) writes:
|> Why is it allowed that a "case" statement doesn't have to be in the
|> immediately-enclosing block of its "switch" statement? Is it just
|> for C-compatibility (to perserve Duff's Device)? Doesn't this
|> screw-up compiler parsing?
I suspect that even in C, the main reason is that it just happened to
fall out that way, and afterwards, nobody thought it important enough to
change. Preserving the legality of Duff's device is probably *not* a
real motivation for anyone, but a change is a change, and should only be
undertaken if it has real benefits. When was the last time you actually
ran into an error that the change would have caught.
What might be useful would be to have a real switch statement that
worked, with the cases requiring (or implicitly defining) separate
blocks. This would avoid the surprise that occurs when one tries to
declare a local variable with an initializer in one of the cases. This
is also a much bigger modification -- it means *no* fall through, so you
would also have to define a new way of specifying multiple cases. To
date, I guess most people have simply thought that there were more
important things to do. At any rate, as far as I know, neither the C
nor the C++ committees have ever received such a proposal.
--=20
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Balog Pal" <pasa@lib.hu>
Date: Mon, 11 Sep 2000 12:59:02 GMT Raw View
<kanze@gabi-soft.de> wrote in message
>>
What might be useful would be to have a real switch statement that
worked, with the cases requiring (or implicitly defining) separate
blocks. This would avoid the surprise that occurs when one tries to
declare a local variable with an initializer in one of the cases. This
is also a much bigger modification -- it means *no* fall through, so you
would also have to define a new way of specifying multiple cases. To
date, I guess most people have simply thought that there were more
important things to do. At any rate, as far as I know, neither the C
nor the C++ committees have ever received such a proposal.
<<
I was thinking about one, but decided it would hardly be considered
seriously, as those things you can do for yourself using the tools at hand.
For switch I actually use this layout:
switch(var)
{
case 'A':
{
//TODO: code goes here
}
break;
case 'B':
{
//TODO: code goes here
}
break;
default:
{
//TODO: code goes here
}
break;
}
No surprises about jump-over initialization, and no accidental crosstalk. If
intended, certainly multiple labels can appear at a single block (that one
should be preserved as common good case), and fallthtough by commentong out
a break.
Paul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]