Topic: Switch and case syntax restriction


Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Tue, 16 Oct 2007 18:37:04 GMT
Raw View
I am wondering why it is not allowed to have a non constant number as
the switch and case expressions.
I see no reason why this shouldn't be allowed. I think that unless I
missed something, it should be added to the language.

I asked ##c++ on freenode once, and they had the following reasons:

* It is syntactic sugar.
I do not think it matters if it would be syntactic sugar, the for loop
is at the very least as much syntactic sugar.

* It is needed to allow the compiler to optimize the code.
True, the compiler can optimize the code with this rule.
But in my opinion, it is just a special optimization and should still be
allowed for code where the old rule is not broken.
But I think that the compiler still can optimize even with more liberal
rules.

I have also personally thought about it and what consequences it would have.

It would, for complex expressions, require that each expression is
evaluated in the precise order that the cases is listed.
I compare this to the short circuiting boolean operators. It would be a
documented feature, not undefined behavior.

This, while not to favorable for binary tree search algorithms and
similar, would not be an issue. I think that under certain
circumstances, you could even optimize it to such search trees.

I have further thought about how this would impact existing code. I
think that there is no valid code that would become invalid.

I have even thought about that the expressions might cause exceptions. I
compare this to how an exception is handled in an if statement and
similar. I think that the same exception rules would apply.

I have also considered operator overloading rules. I think that the
switch case should invoke the == overloaded function. This is remotely
similar to the = operator in the copy semantics and so on.

To summary, I can not find a single reason for this to be forbidden. If
you think of one, please do post it, I am eager to listen.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 16 Oct 2007 21:22:31 GMT
Raw View
Henrik Andersson wrote:
> To summary, I can not find a single reason for this to be forbidden.

You actually gave the reasons yourself. It is syntactic sugar only,
whereas the constant case labels allow for considerable optimization.
Your suggestion of using operator== for the comparisons will fail in
a particular situation that everyone might like have work, namely case
labels which are constant strings against an expression which is a
char pointer. You have not described the type constraints on the case
labels with respect to the switch expression; may they be different?
(You may be able to rip-off the exception handling type matching specs
for this, though.)

In short, this suggestion is a non-starter.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: bop@gmb.dk ("Bo Persson")
Date: Tue, 16 Oct 2007 23:22:39 GMT
Raw View
Henrik Andersson wrote:
:: I am wondering why it is not allowed to have a non constant number
:: as
:: the switch and case expressions.
:: I see no reason why this shouldn't be allowed. I think that unless
:: I
:: missed something, it should be added to the language.
::
:: I asked ##c++ on freenode once, and they had the following reasons:
::
:: * It is syntactic sugar.
:: I do not think it matters if it would be syntactic sugar, the for
:: loop
:: is at the very least as much syntactic sugar.
::
:: * It is needed to allow the compiler to optimize the code.
:: True, the compiler can optimize the code with this rule.
:: But in my opinion, it is just a special optimization and should
:: still be allowed for code where the old rule is not broken.
:: But I think that the compiler still can optimize even with more
:: liberal rules.
::
:: I have also personally thought about it and what consequences it
:: would have.
::
:: It would, for complex expressions, require that each expression is
:: evaluated in the precise order that the cases is listed.
:: I compare this to the short circuiting boolean operators. It would
:: be a documented feature, not undefined behavior.

But this turns the switch statement into another way of writing

if (switch_value == first_condition)
{

}
else if (switch_value == second_condition)
{

}
else if (etc...


What's the point of having two ways of doing this?



Bo Persson



---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Zara <yozara@terra.es>
Date: Wed, 17 Oct 2007 09:38:23 CST
Raw View
On Tue, 16 Oct 2007 18:37:04 GMT, henke@henke37.cjb.net (Henrik
Andersson) wrote:

>I am wondering why it is not allowed to have a non constant number as
>the switch and case expressions.
>I see no reason why this shouldn't be allowed. I think that unless I
>missed something, it should be added to the language.
>
>I asked ##c++ on freenode once, and they had the following reasons:
>
>* It is syntactic sugar.
>I do not think it matters if it would be syntactic sugar, the for loop
>is at the very least as much syntactic sugar.
>
>* It is needed to allow the compiler to optimize the code.
>True, the compiler can optimize the code with this rule.
>But in my opinion, it is just a special optimization and should still be
>allowed for code where the old rule is not broken.
>But I think that the compiler still can optimize even with more liberal
>rules.
>
>I have also personally thought about it and what consequences it would have.
>
>It would, for complex expressions, require that each expression is
>evaluated in the precise order that the cases is listed.
>I compare this to the short circuiting boolean operators. It would be a
>documented feature, not undefined behavior.
>
>This, while not to favorable for binary tree search algorithms and
>similar, would not be an issue. I think that under certain
>circumstances, you could even optimize it to such search trees.
>
>I have further thought about how this would impact existing code. I
>think that there is no valid code that would become invalid.
>
>I have even thought about that the expressions might cause exceptions. I
>compare this to how an exception is handled in an if statement and
>similar. I think that the same exception rules would apply.
>
>I have also considered operator overloading rules. I think that the
>switch case should invoke the == overloaded function. This is remotely
>similar to the = operator in the copy semantics and so on.
>
>To summary, I can not find a single reason for this to be forbidden. If
>you think of one, please do post it, I am eager to listen.
>

If switch may be used with variables for each case statement, there
might be the possibliity of having two variables with the same value,
so you must specify which is the desired behaviour: the first one? the
last one? both? UB?

As this last questions is really difficult to answer, it is robably
better to leave switch statement as it is.

Best regards,

Zara

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: cbarron413@adelphia.net (Carl Barron)
Date: Wed, 17 Oct 2007 16:38:35 GMT
Raw View
In article <rl7Ri.11531$ZA.7557@newsb.telia.net>, Henrik Andersson
<henke@henke37.cjb.net> wrote:

>
> To summary, I can not find a single reason for this to be forbidden. If
> you think of one, please do post it, I am eager to listen.
 With compile time constants as case values the code selector can be
determined from the case values, using a jump table and indirect jump
[plain jump table, or indexed jump table, or even a combo.]. It does not
exclude an explict test but does allow reordering of the tests so the
exceptions can be handled easily
   switch(i)
   {
   case 0: foo_1();break;
   case 1: foo_2();break;
   case  1000: foo_1000();
   case  2 : foo_3();break;

   can be compiled int this pseudo code
   typedef void (*PF)() ;
   PF table[3] = {foo_1,foo_2,foo_3};
   if(I>=0 && i <3)
      (*table[i])()
   else if(i==1000)
      foo_1000();

note that foo_1000 falls into foo_2.  and this
requires at most 3 tests most likely 2 if case 0-2
are more likely. note also it could check ranges
and reorder any tests to get a compact test tree,
or compact table of code chunks.

   load r1,i
   jump_negative  defaults_
   cmpi r1,=3
   jmp_not_neg test_1000
   load r1,table(r1)
   indirect_jump r1
test_1000:
   jump foo_1000;
defaults_:
   ...
   jump_exit_switch
foo_1:  code for case 0
      jump exit_switch
foo_2: code for case 1;
      jump exit_switch
foo_1000:code for case 1000
foo_3:  code for case 2
exit_switch:
do this with runtime case values.

similiar code is possible for indexed jump tables containing
a case value and address to jump to.
if this table is sorted at compile time then advantage can
be taken of the sorted order. [compile time consts mean no
side effects in determining case code]

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Wed, 17 Oct 2007 20:34:46 GMT
Raw View
Carl Barron wrote:
> In article <rl7Ri.11531$ZA.7557@newsb.telia.net>, Henrik Andersson
> <henke@henke37.cjb.net> wrote:
>
>> To summary, I can not find a single reason for this to be forbidden. If
>> you think of one, please do post it, I am eager to listen.
>  With compile time constants as case values the code selector can be
> determined from the case values, using a jump table and indirect jump
> [plain jump table, or indexed jump table, or even a combo.]. It does not
> exclude an explict test but does allow reordering of the tests so the
> exceptions can be handled easily

I fully thought about that optimization, and i addressed it in the
initial post.
Compile time optimization for code that softly follow the old rules
would still be possible, it would not prevent this kind of optimization
for those cases.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Wed, 17 Oct 2007 20:35:35 GMT
Raw View
Bo Persson wrote:
> But this turns the switch statement into another way of writing
>
> if (switch_value == first_condition)
> {
>
> }
> else if (switch_value == second_condition)
> {
>
> }
> else if (etc...
>
>
> What's the point of having two ways of doing this?
>
>
>
> Bo Persson

What is the point of having the for loop when you can do the same thing
with a while loop and code placed at the right places?

It is nicer syntax.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Wed, 17 Oct 2007 21:13:47 GMT
Raw View
Zara wrote:
> If switch may be used with variables for each case statement, there
> might be the possibliity of having two variables with the same value,
> so you must specify which is the desired behaviour: the first one? the
> last one? both? UB?
>
> As this last questions is really difficult to answer, it is robably
> better to leave switch statement as it is.
>
> Best regards,
>
> Zara

A very valid concern, but is there a rule that already specifies this?
If not, the most logical thing would be to require the first and only
the first case that matches to be the one to execute.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Wed, 17 Oct 2007 21:14:13 GMT
Raw View
Hyman Rosen wrote:
> Henrik Andersson wrote:
>> To summary, I can not find a single reason for this to be forbidden.
>
> You actually gave the reasons yourself. It is syntactic sugar only,
> whereas the constant case labels allow for considerable optimization.
> Your suggestion of using operator== for the comparisons will fail in
> a particular situation that everyone might like have work, namely case
> labels which are constant strings against an expression which is a
> char pointer. You have not described the type constraints on the case
> labels with respect to the switch expression; may they be different?
> (You may be able to rip-off the exception handling type matching specs
> for this, though.)
>
> In short, this suggestion is a non-starter.

I have to agree, it is a pity that char pointers would not be possible
to match for the pointed at strings, but so is the rules for the normal
== operator.
The thing is, stl got this nifty std::string class that we can use...

About the different type issue, it would be the same as for the normal
== rules, if switch-expression == case-expression is defined, it would
be valid. So, if the types could normally be compared, it would be
valid, same type or not.

About the optimization, read another reply I wrote.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Wed, 17 Oct 2007 23:32:41 GMT
Raw View
Henrik Andersson wrote:
> It is nicer syntax.

Most of the original languages that have these constructs
have them with constant labels, and therefore the order of
the cases is immaterial. In fact, in Ada, the compiler will
give you an error if the statement does not exhaust all
possible values of the expression type.

Adding the new form of the statement would now make the
order of the labels significant. That's a semantic overhead
that I'd rather not bear just for a (dubiously) nicer syntax.
You could try submitting a proposal to the committee, but I'm
certain it would get voted down.

Maybe you can use macros? You'll need a compiler with the new
auto syntax.

     #define MATCH(e) { auto const &match_value = (e); if (false)
     #define WHEN(l) } else if (match_value == (l)) {
     #define DEFAULT } else

     MATCH(string("hello"))
     {
     WHEN("abc")
         cout << "abc";
     WHEN("def")
         cout << "def";
     WHEN("hello")
         cout << "hello";
     DEFAULT
         cout << "something else";
     }

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Thu, 18 Oct 2007 08:35:57 GMT
Raw View
Hyman Rosen wrote:
> Adding the new form of the statement would now make the
> order of the labels significant. That's a semantic overhead
> that I'd rather not bear just for a (dubiously) nicer syntax.

Why? Do you think it would be too much work for the compiler authors?
The standards usually don't get implemented even closely to fully until
a new standard is defined.

> You could try submitting a proposal to the committee, but I'm
> certain it would get voted down.

Why do you think that?

> Maybe you can use macros? You'll need a compiler with the new
> auto syntax.
>
>     #define MATCH(e) { auto const &match_value = (e); if (false)
>     #define WHEN(l) } else if (match_value == (l)) {
>     #define DEFAULT } else
>

Sorry to be picky, but that does not support the fallthru system.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 18 Oct 2007 17:24:29 GMT
Raw View
Henrik Andersson wrote:
> Hyman Rosen wrote:
>> That's a semantic overhead> that I'd rather not bear
>
> Why? Do you think it would be too much work for the compiler authors?

No, for readers of the code. All these questions about the
semantics of the construct don't just need to be handled by
the implementors, they need to be understood by the readers
of the code.

>> I'm certain it would get voted down.
>
> Why do you think that?

Because I've worked with C and C++ for some thirty years
and I like to think I have a feel for the kinds of things
that people skilled in the languages will accept. The
reaction I foresee is "it doesn't gain anything useful and
it's too hard to describe and understand". I don't believe
you can convince enough people otherwise to get it to pass.
If I were on the committee, I would vote "no".

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Thu, 18 Oct 2007 20:43:05 GMT
Raw View
Hyman Rosen wrote:
> Henrik Andersson wrote:
>> Hyman Rosen wrote:
>>> That's a semantic overhead> that I'd rather not bear
>>
>> Why? Do you think it would be too much work for the compiler authors?
>
> No, for readers of the code. All these questions about the
> semantics of the construct don't just need to be handled by
> the implementors, they need to be understood by the readers
> of the code.
>

You do have a point, but wont the people who decide to use this newer
standard be expected to know how to learn the new parts?
And it's not like I am inventing a new operator, just a more general
usage of an existing structure.
Most people will get what the code is doing immedialy.

>>> I'm certain it would get voted down.
>>
>> Why do you think that?
>
> Because I've worked with C and C++ for some thirty years
> and I like to think I have a feel for the kinds of things
> that people skilled in the languages will accept. The
> reaction I foresee is "it doesn't gain anything useful and
> it's too hard to describe and understand". I don't believe
> you can convince enough people otherwise to get it to pass.
> If I were on the committee, I would vote "no".

It is not too hard to describe, I just did. And evidently, you understood.
And what do you think that these people would use as concrete reasons to
not pass it?

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "Nevin :-] Liber" <nevin@eviloverlord.com>
Date: Fri, 19 Oct 2007 11:58:51 CST
Raw View
In article <b9PRi.11673$ZA.7630@newsb.telia.net>,
 henke@henke37.cjb.net (Henrik Andersson) wrote:

> It is not too hard to describe, I just did.

Not with nearly enough rigor to be a standards proposal.

Suppose I had the following class:

struct MyInt
{
   operator int() const { return i + 1; }

   bool operator==(int j) const { return i == j; }

   int i;
};

//...

MyInt mi;
//...
switch (mi)
{
case 1:
   DoSomething();
   break;
case 2:
   DoSomethingElse();
   break;
}

What are the semantics of the above?  What are the semantics if I make
any combination of the following changes:
1.  Remove operator int from MyInt
2.  Remove operator== from MyInt
3.  Make the case labels variables instead of constants
4.  Make the case labels const variables
5.  Allow operator== to modify the internal state of MyInt
6.  Allow operator int to modify the internal state of MyInt
Etc., etc.

Is it still 100% backwards compatible?  I've only thought about this for
a few minutes; have I even covered all the possibilities yet?

> And evidently, you understood.

The devil is in the details.  And it is an awful lot of details to get
right for something that, quite frankly, isn't more than syntactic sugar
over if/else.  Worse, it make all switch statements harder to read, as
one now has to understand the type of every label and variable being
switched upon before I know its semantics.

--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  773 961-1620

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Zara <yozara@terra.es>
Date: Fri, 19 Oct 2007 15:08:36 CST
Raw View
On Wed, 17 Oct 2007 21:13:47 GMT, henke@henke37.cjb.net (Henrik
Andersson) wrote:

>Zara wrote:
>> If switch may be used with variables for each case statement, there
>> might be the possibliity of having two variables with the same value,
>> so you must specify which is the desired behaviour: the first one? the
>> last one? both? UB?
>>
>> As this last questions is really difficult to answer, it is robably
>> better to leave switch statement as it is.
>>
>
>A very valid concern, but is there a rule that already specifies this?
>If not, the most logical thing would be to require the first and only
>the first case that matches to be the one to execute.

Why? Using the last might be as valid a rule, and it should probably
have its own defendants. I would defend UB, as a normal switch won   t
compile on repeated cases.

Bets regards,

Zara

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Fri, 19 Oct 2007 20:08:32 GMT
Raw View
Nevin :-] Liber wrote:
> In article <b9PRi.11673$ZA.7630@newsb.telia.net>,
>  henke@henke37.cjb.net (Henrik Andersson) wrote:
>
>> It is not too hard to describe, I just did.
>
> Not with nearly enough rigor to be a standards proposal.
>
> Suppose I had the following class:
>
> struct MyInt
> {
>    operator int() const { return i + 1; }
>
>    bool operator==(int j) const { return i == j; }
>
>    int i;
> };
>
> //...
>
> MyInt mi;
> //...
> switch (mi)
> {
> case 1:
>    DoSomething();
>    break;
> case 2:
>    DoSomethingElse();
>    break;
> }
>
> What are the semantics of the above?

I will assume that you omitted the initialization of MyInt::i for
brevity and that it can be any valid int, not 1 in all cases or 2 in all
cases.

Same as:
if(mi==1) {
    DoSomeThing();
} else if(mi==2) {
    DoSomethingElse();
}

The operator(int) is not invoked, since the operator== got a specific
prototype for this case. This is different from how it currently would work!

What are the semantics if I make
> any combination of the following changes:
> 1.  Remove operator int from MyInt

Same as first example.

> 2.  Remove operator== from MyInt

operator(int) would be invoked.

> 3.  Make the case labels variables instead of constants

They would be read just before the comparison would be made

> 4.  Make the case labels const variables

See 3., they are read just before comparing.

> 5.  Allow operator== to modify the internal state of MyInt

It would do the modification, and it would last, assuming that the
compared expressions was going to last anyway.

> 6.  Allow operator int to modify the internal state of MyInt

Assuming it is invoked at all, it would be allowed to do the modification.

>
> Is it still 100% backwards compatible?  I've only thought about this for
> a few minutes; have I even covered all the possibilities yet?

Ok, there is one semantic change, if there is an operator(int) and a
matching operator==, previously the operator(int) would be invoked, but
after this change, operator== would be invoked instead. Good that you
brought up the conversion operators, since I didn't know about them.

I think that it would be a rather bad design if this semantic change
would effect any program. Also, this very issue would be similar in
effect to doing if(int==object), just that the operator== has priority
both before and after the change.

I must admit that I did not know of the conversation operators, but you
never stop learning.

> Worse, it make all switch statements harder to read, as
> one now has to understand the type of every label and variable being
> switched upon before I know its semantics.

If people stopped doing crazy operator overloadings, the problem would
be void.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Fri, 19 Oct 2007 21:52:16 GMT
Raw View
Zara wrote:
> Why? Using the last might be as valid a rule, and it should probably
> have its own defendants. I would defend UB, as a normal switch won=B4t
> compile on repeated cases.
>=20
> Bets regards,
>=20
> Zara
>=20

Maybe you should consider that the rest of c++ uses top to bottom=20
instruction ordering.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: jdennett@acm.org (James Dennett)
Date: Sat, 20 Oct 2007 01:05:54 GMT
Raw View
Henrik Andersson wrote:
> Zara wrote:
>> Why? Using the last might be as valid a rule, and it should probably
>> have its own defendants. I would defend UB, as a normal switch won=B4t
>> compile on repeated cases.
>>
>> Bets regards,
>>
>> Zara
>>
>=20
> Maybe you should consider that the rest of c++ uses top to bottom
> instruction ordering.

switch (3)
{
  default: throw 7;
  case 3:  break;
}

switch doesn't use top-to-bottom ordering today: apart from
when falling through, the order of cases has no effect, and
many learning C++ are surprised that default is not required
to follow all other cases.

-- James

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: nevin@eviloverlord.com ("Nevin :-] Liber")
Date: Sat, 20 Oct 2007 17:31:34 GMT
Raw View
In article <4t7Si.11734$ZA.7719@newsb.telia.net>,
 henke@henke37.cjb.net (Henrik Andersson) wrote:

> Nevin :-] Liber wrote:
> > struct MyInt
> > {
> >    operator int() const { return i + 1; }
> >
> >    bool operator==(int j) const { return i == j; }
> >
> >    int i;
> > };
> >
> > //...
> >
> > MyInt mi;
> > //...
> > switch (mi)
> > {
> > case 1:
> >    DoSomething();
> >    break;
> > case 2:
> >    DoSomethingElse();
> >    break;
> > }
>
> Same as:
> if(mi==1) {
>     DoSomeThing();
> } else if(mi==2) {
>     DoSomethingElse();
> }
>
> The operator(int) is not invoked, since the operator== got a specific
> prototype for this case. This is different from how it currently would work!

And you still believe there would be any chance of getting this into the
standard?  Breaking backwards compatibility (and silently at that) is
not something the committee ever takes lightly.

It's even worse.  Many times switch is implemented as O(1) or O(log n),
depending on the density of the labels.  Your pessimization is O(n),
unless you have inlining and aggressive optimization.

> I think that it would be a rather bad design if this semantic change
> would effect any program.

That is irrelevant.  Your change silently breaks existing, working
programs.  Even if it doesn't break them, it slows them down.

> I must admit that I did not know of the conversation operators, but you
> never stop learning.

If you wish to propose language changes, you really need to learn the
language in depth.

> > Worse, it make all switch statements harder to read, as
> > one now has to understand the type of every label and variable being
> > switched upon before I know its semantics.
>
> If people stopped doing crazy operator overloadings, the problem would
> be void.

There are lots of reasons people overload operators, which have nothing
to do with being crazy.  For instance, people will add an operator< to
their class so that they can be easily stored in a set or as a key in a
map, even though an ordering makes no other sense for the class.

--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  773 961-1620

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Henrik Andersson <henke@henke37.cjb.net>
Date: Sat, 20 Oct 2007 18:17:18 CST
Raw View
James Dennett wrote:
> Henrik Andersson wrote:
>> Zara wrote:
>>> Why? Using the last might be as valid a rule, and it should probably
>>> have its own defendants. I would defend UB, as a normal switch won   t
>>> compile on repeated cases.
>>>
>>> Bets regards,
>>>
>>> Zara
>>>
>> Maybe you should consider that the rest of c++ uses top to bottom
>> instruction ordering.
>
> switch (3)
> {
>   default: throw 7;
>   case 3:  break;
> }
>
> switch doesn't use top-to-bottom ordering today: apart from
> when falling through, the order of cases has no effect, and
> many learning C++ are surprised that default is not required
> to follow all other cases.

Well, with this change, if there is ambiguity, an order is needed.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: henke@henke37.cjb.net (Henrik Andersson)
Date: Sun, 21 Oct 2007 14:23:40 GMT
Raw View
Nevin :-] Liber wrote:
> And you still believe there would be any chance of getting this into the
> standard?  Breaking backwards compatibility (and silently at that) is
> not something the committee ever takes lightly.
>
> It's even worse.  Many times switch is implemented as O(1) or O(log n),
> depending on the density of the labels.  Your pessimization is O(n),
> unless you have inlining and aggressive optimization.
>


About that slow down, O(n) is the worst case scenario. For code that
follows soft rules, you can get those nifty O(1) and O(log n)
optimizations, since the soft rules guarantees that they are safe to do.

If all the comparisons is on the same type and are marked as const, the
compiler would be allowed to make a binary search tree as with the
current rules. But, this is not the only rule that optimizations can
use. But I will limit myself to it for the discussion.

Besides, switch cases is usually relatively tiny compared to the maximum
  case count. There isn't usually too much to optimize.

This doesn't mean your point is moot, speed can suffer if no soft rule
can be applied. Virtual methods is the same, the compiler is smart
enough to only make you pay the price if it is truly needed.

This is no real argument, but I don't think that switch cases is going
to be in the most performance critical loop most of the time.

 >> I think that it would be a rather bad design if this semantic change
 >> would effect any program.
 >
 > That is irrelevant.  Your change silently breaks existing, working
 > programs.  Even if it doesn't break them, it slows them down.

About that backwards breaking, I do not plan on getting this into the
current major version of the language. More like the object semantics in
php 4 vs php 5.
The summary of the php change is that php 4 treats object variables as
directly contained structs, while php 5 treats them as pointers to
structs. This broke a few applications, but they believed the positive
aspects was greater then the negative ones.
I think that the people that has an operator(int) and uses the object as
the switch expression is mainly trying to fake what I am proposing.

> If you wish to propose language changes, you really need to learn the
> language in depth.
You do have a point there. But some things are invented/discovered by
fools who don't know a lot. Peer review is what makes sure things is
properly done. I posted this proposal here to get peer review.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "Nevin :-] Liber" <nevin@eviloverlord.com>
Date: Sun, 21 Oct 2007 14:17:10 CST
Raw View
In article <zPFSi.11837$ZA.7823@newsb.telia.net>,
 henke@henke37.cjb.net (Henrik Andersson) wrote:

> About that slow down, O(n) is the worst case scenario. For code that
> follows soft rules, you can get those nifty O(1) and O(log n)
> optimizations, since the soft rules guarantees that they are safe to do.
>
> If all the comparisons is on the same type and are marked as const, the
> compiler would be allowed to make a binary search tree as with the
> current rules.

Const is not sufficient (and never has been) to allow the compiler to
make a binary search tree.  Things like mutable, const_cast, static and
global variables get in the way.  The compiler has to determine that the
object itself doesn't change and that no externally visible state
changes before it can perform this optimization.  Plus, in order to
store it in a tree, you are now requiring an operator< (or equivalent)
which imposes a total ordering as well as an operator==.  That would,
for instance, rule out std::complex numbers.  Heck, that technically
leaves out floating point numbers, since they are not totally ordered
due to NaN.

Under most compilers, just putting the implementation of operator== in a
.cpp instead of a header would be sufficient to make it O(n).

The current switch statement needs none of that to make the optimization.

> Besides, switch cases is usually relatively tiny compared to the maximum
>   case count. There isn't usually too much to optimize.

Duff's Device is a counterexample to that claim.  Also, if it is inside
a loop, it can easily change an algorithm from O(n) to O(n^2).

> This broke a few applications, but they believed the positive
> aspects was greater then the negative ones.

You haven't shown that for this change.

> I think that the people that has an operator(int) and uses the object as
> the switch expression is mainly trying to fake what I am proposing.

Don't assume you know why the rest of us make the design decisions that
we do.

> > If you wish to propose language changes, you really need to learn the
> > language in depth.
> You do have a point there. But some things are invented/discovered by
> fools who don't know a lot.

It isn't like this is the first time someone in a newsgroup proposed
extending switch.  Heck, I'd be surprised if it was the first time this
year.  It isn't hard to check out the history and learn from it.

> Peer review is what makes sure things is
> properly done.

And so far, all the peers have told you the it won't fly because the
drawbacks far outweigh any benefits.  And we are finding the drawbacks
doing just "armchair quarterbacking".


Good luck.  If you are willing to write up a rigorous proposal, and then
attend multiple committee meetings for a few years to push for this
change, maybe you will have a chance of beating the odds and getting it
adopted.

--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  773 961-1620

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: nagle@animats.com (John Nagle)
Date: Sun, 21 Oct 2007 22:06:27 GMT
Raw View
Henrik Andersson wrote:
> Bo Persson wrote:
>> But this turns the switch statement into another way of writing
>>
>> if (switch_value == first_condition)
>> else if (switch_value == second_condition)
>> else if (etc...

    Look up Djkystra's "guards".  This idea dates from the 1970s.
Djkystra's answer to the ordering issue was that if more than one
case evaluated to true, one should be chosen at random.  That
idea had a certain theoretical elegance but did not catch on.

    The other bad switch-related idea from that era was Wirth's insistence
that the Pascal case statement should not have a default, on the grounds
that such a feature would encourage bad programming.  Really.
That was in a language that had integer subranges and real enums,
so exhaustive case statements were possible.

     John Nagle

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: jpalecek@web.de (Jiri Palecek)
Date: Sun, 21 Oct 2007 23:59:47 GMT
Raw View
<posted & mailed>

Nevin :-] Liber wrote:

> In article <zPFSi.11837$ZA.7823@newsb.telia.net>,
> changes before it can perform this optimization.  Plus, in order to
> store it in a tree, you are now requiring an operator< (or equivalent)
> which imposes a total ordering as well as an operator==.  That would,
> for instance, rule out std::complex numbers.  Heck, that technically
> leaves out floating point numbers, since they are not totally ordered
> due to NaN.

Technically speaking, everything in the computer can be ordered by taking a
bit-string representation of it and lexicographically ordering it. (And
assuming the axiom of choice every set can be ordered.) However, you are
right that this ordering is certainly not good enough for defining
operator<, although it would suffice for switch if it needed exact match,
and I would consider a switch depending on exact match of floats perverse.
For floats, maybe some range-switch (where you would partition the real
line to a set of intervals and make decisions based on membership of a
value in these intervals) would be appropriate, which is however quite far
even from the proposal of OP.

Regards
    Jiri Palecek

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: jcoffin@taeus.com (Jerry Coffin)
Date: Mon, 22 Oct 2007 04:01:03 GMT
Raw View
In article <ffglj1$1vk$2@ns.felk.cvut.cz>, jpalecek@web.de says...

[ ... ]

> Technically speaking, everything in the computer can be ordered by taking a
> bit-string representation of it and lexicographically ordering it. (And
> assuming the axiom of choice every set can be ordered.) However, you are
> right that this ordering is certainly not good enough for defining
> operator<, although it would suffice for switch if it needed exact match,
> and I would consider a switch depending on exact match of floats perverse.

It doesn't work for an exact match of floats in any case (at least not
for the usual IEEE formats). Just for example, with IEEE floating point,
there are a large number of different bit patterns that all signify
exactly 0.0. There's also the fact that under normal circumstances, a
NaN should NOT compare as equal to anything, even another NaN with the
same bit pattern.

> For floats, maybe some range-switch (where you would partition the real
> line to a set of intervals and make decisions based on membership of a
> value in these intervals) would be appropriate, which is however quite far
> even from the proposal of OP.

IMO, it's generally better to just stay away from the whole notion
entirely.

--
    Later,
    Jerry.

The universe is a figment of its own imagination.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Charles Bailey <usenetspam01@hashpling.org>
Date: Mon, 22 Oct 2007 08:07:27 CST
Raw View
On 2007-10-21, Jiri Palecek <jpalecek@web.de> wrote:
> Technically speaking, everything in the computer can be ordered by taking a
> bit-string representation of it and lexicographically ordering it. (And
> assuming the axiom of choice every set can be ordered.)

Given that all current C implementations are on computers which have a
finite address space the axiom of choice is unnecessary: your
bit-string representation with lexicographical ordering can be used to
define a total ordering of 'everything in the computer'.  The axiom of
choice is also not necessary for computers which operate on countably
infinite numbers of objects of countably infinite size.

On the topic, I don't think that there is anything wrong with the
current switch / case usage.  Most C++ users that I know think of a
switch in terms of an efficient way of selecting between multiple
branches and imagine that they are likely to get an efficient jump
table style implementation when they use it.

If a more complex evaluation and comparison is required then I would
prefer to code what I mean.  I would also prefer not to have any
features that unnecessarily widen the gap between C and C++ either in
syntax or in meaning.

--
Charles Bailey
http://ccgi.hashpling.plus.com/blog/

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Mon, 22 Oct 2007 08:08:12 CST
Raw View
On Oct 22, 6:01 am, jcof...@taeus.com (Jerry Coffin) wrote:
> In article <ffglj1$1v...@ns.felk.cvut.cz>, jpale...@web.de says...

> [ ... ]

> > Technically speaking, everything in the computer can be ordered by taking a
> > bit-string representation of it and lexicographically ordering it. (And
> > assuming the axiom of choice every set can be ordered.) However, you are
> > right that this ordering is certainly not good enough for defining
> > operator<, although it would suffice for switch if it needed exact match,
> > and I would consider a switch depending on exact match of floats perverse.

> It doesn't work for an exact match of floats in any case (at least not
> for the usual IEEE formats). Just for example, with IEEE floating point,
> there are a large number of different bit patterns that all signify
> exactly 0.0.

Just two.  IEEE supports gradual underflow, and the only "exact"
0.0's have both mantissa and exponent 0 (but sign bit is still
don't care).  Most other floating point formats I've seen,
however, treat anything with an exponent field of 0 as exactly
0.0.

It gets even more complex with user defined types, however.  I
regularly use a Fallible: basically a bool plus a value, where,
if the bool if false, the value isn't valid---and for built in
types like double, contains random garbage.

    [...]
> IMO, it's generally better to just stay away from the whole
> notion entirely.

Agreed.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/csc/faq.html                      ]