From: mccauleyba@vax1.bham.ac.uk (Brian McCauley)
Subject: Re: Proposal - enhancement for switch statement.
Date: Mon, 16 Nov 1992 21:30:15 GMT
Organization: University of Birmingham

In article <1992Nov16.004558.9855@muddcs.claremont.edu>, dfoster@jarthur.claremont.edu (Derek R. Foster) writes:
> In article <MCGRANT.92Nov15132747@rascals.stanford.edu> mcgrant@rascals.stanford.edu (Michael C. Grant) writes:
>>In article <1992Nov15.190830.11622@cssc-syd.tansu.com.au>
>>pete@cssc-syd.tansu.com.au (Peter Alexander Merel) writes:
>>   ...
>>   switch to use operator== rather than relying on conversion to int, so that 
>>   I could use it to test cases on objects rather than building an industrial 
>>   strength if statement. 
> ...
> Personally, I would like to see a few more changes made to the 'switch'
> statement (in my opinion, one of the ugliest warts on the face of the
> C language, and regrettably C++ also.)
> 
> I wouldn't advise actually getting rid of the 'switch' statement (it is
> needed for backwards compatibility), but instead creating a (somewhat) 
> parallel statement, called, say, 'switchc'.
                                    ^^^^^^^
No. Please not another token in the parser.
> 
>   1) Remove the requirement for a 'break' after each statement (the accidental
>      omission of which is the cause of a ridiculously large number of errors
>      within C programs.) Make a 'break' the default, rather than fallthrough
>      being the default. Add a 'fallthrough' keyword (or extend the
>      meaning of the 'continue' keyword perhaps?) to still allow programmers
>      to use fallthrough in those rare occasions for which it is necessary/
>      desirable.
I agree the default behavior is wrong but were all used to it so lets keep it.
All that is needed is to _advise_ compiler implementors that they should
give a warning if `case' (or `default') is preceded by anything other than
`break;' or `case:' (except of course the first one). Good C++ programmers
treat warnings as errors unless they are compling C sources.
While were about it perhaps we should point out that compliers should warn
when variables defined in one case are used in another (IMHO each case
should always be given it's own scope).
> 
>   2) Allow multiple labels for each 'case' statement, and extend the case
>      statement to allow ranges and multiple arguments (as in Pascal.) This
>      avoids the excessively verbose lists of 'case' statements that are
>      necessary in C to represent ranges of values.
Multiple arguments - agian I'd agree if we were inventing a language from
scratch but I'm not sure there's any need to change the syntax for
a saving of 3 characters. Likewise for ranges would (see below).
> 
> as per Peter's suggestion, we could easily add...
> 
>   3) for class-typed switching variables, we could require that 'switchc' 
>      use operator == and a simple linear search to work its way down the
>      list. (yes, this is possibly inefficient. It is, however, extremely
>      clear code which is easy to read.) In the case of non-class-typed
>      switching variables, the compiler is allowed to use a jump table,
>      binary search, or whatever seems appropriate.
>   4) in implementing 3, we could allow, for class typed variables, the
>      switch labels to be any data type for which operator == with the
>      given class type is defined. For instance, char *'s, floating point
>      values, (references to const objects?,) etc.
   ...
>                           ...using 'if's, it is a) much harder to
>     read, b) much harder to understand (the reader may not immediately
>     see the overall structure), and c) more error-prone (it is possible to
>     get mismatched 'else's, etc. which will compile fine, but not do
>     what they're supposed to.
> 
>     I would LOVE to see the addition of something like this to the language.
>     Control flow in many of my programs would be vastly simplified, and I
>     think the number of errors I would make would be substantially smaller.
Yes I agree but let's non pollute _everyones_ namspace by adding a new token.
The only problem is that if a class has both an `operator==(int)' and an
`operator int ()' defined inconsistantly the some existing switch statements
would change their meaning.

Now (as promised) why ranges would be unnecessary (following the "if you
can do it with a class then don't extend the language" rule ;-) )

template <class T> class Range {
  T top,bottom; 
public:
  Range(t,b) : top(t),bottom(b) {} 
  int operator==(T t) { return bottom <= t && top >= t; }
}
template <class T> inline operator == (T& t,Range<T>& r) {return r == t;}

switch (i) {
  case Range<char>('0','9') : case '-' : {/*...*/} break;
}

compare:

switchc (i) {
  case '0'...'9' , '-': /*...*/
}

OK so it's not as concise as your form but it far more C++. Assuming your
compiler supports inlining it can be made to optimize as well as the
explicit range syntax.

BTW heres a new constuct (my mother's favorate in BASIC) that would become
available:

switch(TRUE) {
  case expr1: { /* code */} break;
  case expr2: { /* code */} break;
  delfault: {/* code */}
}

This is exactly equivalent to an if ladder but some people think it looks
nicer :-)
-- 
    \\   ( )    No Bullshit!     |  Email: B.A.McCauley@bham.ac.uk   
 .  _\\__[oo        from         |  Voice: +44 21 471 3789 (home)
.__/  \\ /\@    /~)  /~[   /\/[  |    Fax: +44 21 625 2175 (work)
.  l___\\      /~~) /~~[  /   [  |  Snail: 197 Harborne Lane,
 # ll  l\\    ~~~~ ~   ~ ~    ~  |         Birmingham, B29 6SS, UK
###LL  LL\\   (Brian McCauley)   |   ICBM: 52.5N 1.9W
Newsgroups: comp.lang.c++