 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Prateek R Karandikar Guest
|
Posted: Tue Sep 21, 2004 6:37 pm Post subject: Why must values in case labels be compile-time constants? |
|
|
Why must values in case labels be compile-time constants?
-- --
Abstraction is selective ignorance. -Andrew Koenig
-- --
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Terje Slettebø Guest
|
Posted: Tue Sep 21, 2004 8:18 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
"Prateek R Karandikar" <kprateek88 (AT) yahoo (DOT) com> wrote
| Quote: | Why must values in case labels be compile-time constants?
|
Because the language is defined that way? :)
Seriously, though, I guess there's no fundamental reason you could not
switch on any type being EqualityComparable (having "==" operator). However,
if they are compile-time constants, the compiler might be able to do
optimisations, such as jump tables (using the value to switch on as an index
into a table).
However, what do you use switch for, anyway? Often, one may replace nested
if-else chains, or switch-case, with polymorphism.
Regards,
Terje
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Wed Sep 22, 2004 5:08 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
Prateek R Karandikar wrote:
| Quote: | Why must values in case labels be compile-time constants?
|
So that compilers may implement switch statements using
more efficient methods than sequentially comparing the
expression with each case label.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Al Grant Guest
|
Posted: Wed Sep 22, 2004 5:48 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
[email]tslettebo (AT) hotmail (DOT) com[/email] ("Terje Slettebø") wrote in message news:<415081e3$1 (AT) news (DOT) broadpark.no>...
| Quote: | "Prateek R Karandikar" <kprateek88 (AT) yahoo (DOT) com> wrote in message
news:1095768477.957967.88970 (AT) k17g2000odb (DOT) googlegroups.com...
Why must values in case labels be compile-time constants?
Because the language is defined that way? :)
Seriously, though, I guess there's no fundamental reason you could not
switch on any type being EqualityComparable (having "==" operator).
|
In PL/1, the case expressions are evaluated in order and the
first matching case is taken. It's trivial to implement.
(The compiler can of course optimize with a jump table, hash
table, binary search etc. if all the expressions are constant.)
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
James Dennett Guest
|
Posted: Tue Sep 28, 2004 3:37 am Post subject: Re: Why must values in case labels be compile-time constants |
|
|
Hyman Rosen wrote:
| Quote: | Prateek R Karandikar wrote:
Why must values in case labels be compile-time constants?
So that compilers may implement switch statements using
more efficient methods than sequentially comparing the
expression with each case label.
|
That argument is often used, but of course allowing more
freedom would not cause pessimisation of code that doesn't
exploit that freedom.
It's a shame that C and C++ lack an elegant notation for
a more general switch/case construct, and re-using the
existing syntax would be a way around that, at no cost to
performance of code except when the flexibility is used.
Or should we introduce a notation like
switch not for const case (expr)
<g>
-- 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Daniel Krügler (ne Spange Guest
|
Posted: Tue Sep 28, 2004 3:42 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
Good morning James Dennett
James Dennett schrieb:
| Quote: | It's a shame that C and C++ lack an elegant notation for
a more general switch/case construct, and re-using the
existing syntax would be a way around that, at no cost to
performance of code except when the flexibility is used.
Or should we introduce a notation like
switch not for const case (expr)
g
|
To my opinion a much more appropriate syntax would overload
the static keyword here again, e.g.
~static switch(expr)
For better symmetry we would also extend the good ol' switch with
integral constant labels:
static switch(expr)
;-)
(Sorry mods, but I couldn't resist)
Honestly, what I miss much more "in case" of switch cases is
the ability to provide ranges of values, similar to Pascal's case:
case (what_ever) of
'a'..'y': ;
'0'..'4', '6'..'9':;
'A', 'C', 'M':
end;
C's and C++'s notation for switch cases falling in the same slot
is annoying:
switch (what_ever) {
case 'A': case 'C': case 'M':
break;
case '0': case '1': case '2': case '3': case '4': case '6': case '7':
case '8': case '9':
break;
default: // No!, I don't write each case here!!
if (what_ever >= 'a' && what_ever <= 'y') { // not portable, but that
doesn't count here..
}
}
Greetings from Bremen,
Daniel
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Tue Sep 28, 2004 3:47 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
James Dennett wrote:
| Quote: | That argument is often used, but of course allowing more
freedom would not cause pessimisation of code that doesn't
exploit that freedom.
It's a shame that C and C++ lack an elegant notation for
a more general switch/case construct, and re-using the
existing syntax would be a way around that, at no cost to
performance of code except when the flexibility is used.
|
This "more freedom" would raise questions of precisely when
or if the case labels would be evaluated. I can imagine code
like this:
bool is_0_or_1(int n)
{
int i = 0;
switch(n)
{
default:
return false;
case i++:
case i:
return true;
}
}
Anyway, there is a perfectly elegant notation for the
general case:
const some_type &n = some_complicated_expression();
if (n == first_case) {
} else if (n == second_case) {
} else if (n == third_case) {
} else {
}
The only reason for switch to exist is to represent the
constant-case optimization. It's like the register keyword.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Paul Evans Guest
|
Posted: Tue Sep 28, 2004 10:15 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
James Dennett <jdennett (AT) acm (DOT) org> wrote
[snip]
| Quote: | It's a shame that C and C++ lack an elegant notation for
a more general switch/case construct,
[snip] |
how about:
#include <iostream>
#include <map>
using namespace std;
void case1() { cout << "foo1" << endl; }
void case2() { cout << "foo2" << endl; }
void case3() { cout << "foo3" << endl; }
typedef void (*pfv)();
int main() {
map
dynamic_switch[4] = &case1;
dynamic_switch[6] = &case2;
dynamic_switch[9] = &case3;
int x = 6;
dynamic_switch[x]();
return 0;
}
With obvious extensions/library generalisations.
I'd also change it to use boost::functional
Cheers,
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://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
James Dennett Guest
|
Posted: Wed Sep 29, 2004 6:34 am Post subject: Re: Why must values in case labels be compile-time constants |
|
|
Hyman Rosen wrote:
| Quote: | James Dennett wrote:
That argument is often used, but of course allowing more
freedom would not cause pessimisation of code that doesn't
exploit that freedom.
It's a shame that C and C++ lack an elegant notation for
a more general switch/case construct, and re-using the
existing syntax would be a way around that, at no cost to
performance of code except when the flexibility is used.
This "more freedom" would raise questions of precisely when
or if the case labels would be evaluated. I can imagine code
like this:
bool is_0_or_1(int n)
{
int i = 0;
switch(n)
{
default:
return false;
case i++:
case i:
return true;
}
}
|
Choices: leave it unspecified which items are evaluated and in which
order. There's no need to support side-effects here; people just
want to be able to use known values that may not be compile-time
constants.
| Quote: | Anyway, there is a perfectly elegant notation for the
general case:
const some_type &n = some_complicated_expression();
if (n == first_case) {
} else if (n == second_case) {
} else if (n == third_case) {
} else {
}
|
Duplication is inelegant, as is the use of excessively general
constructs for simple situations. When I see a switch statement,
I know at a glance that the code is testing one value against a
number of different possibilities. When I see an if/else ladder,
all I know is that there are a pile of different conditions being
tested.
| Quote: | The only reason for switch to exist is to represent the
constant-case optimization.
|
I disagree; many other languages have very similar constructs,
and it's far from universal to impose the restriction that C
and C++ do. The biggest value of the notation is its
expressiveness. Compilers can also optimize if/else ladders
if all conditions are comparisons of the same value against
compiler-time constants.
| Quote: | It's like the register keyword.
|
The main value of switch is to human readers; the main value
of register is to simple optimizers (where the restrictions of
switch also have some small value).
-- 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Wed Sep 29, 2004 5:38 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
In article <t5r6d.36683$aW5.9541@fed1read07>, James Dennett
<jdennett (AT) acm (DOT) org> writes
| Quote: | Hyman Rosen wrote:
James Dennett wrote:
That argument is often used, but of course allowing more
freedom would not cause pessimisation of code that doesn't
exploit that freedom.
It's a shame that C and C++ lack an elegant notation for
a more general switch/case construct, and re-using the
existing syntax would be a way around that, at no cost to
performance of code except when the flexibility is used.
This "more freedom" would raise questions of precisely when
or if the case labels would be evaluated. I can imagine code
like this:
bool is_0_or_1(int n)
{
int i = 0;
switch(n)
{
default:
return false;
case i++:
case i:
return true;
}
}
Choices: leave it unspecified which items are evaluated and in which
order. There's no need to support side-effects here; people just
want to be able to use known values that may not be compile-time
constants.
|
I think I would be happy to have a form of switch in which the selection
expressions were pure expressions (ones whose evaluation have no side
effects). The program should be required to evaluate these expressions
as if in the sequence provided by the source code until one of them
compares equal to the control value.
This dynamic version of switch would almost certainly pay in performance
but the advantage of source code clarity should not be ignored.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Robert Kawulak Guest
|
Posted: Wed Sep 29, 2004 9:28 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
Hi,
| Quote: | This "more freedom" would raise questions of precisely when
or if the case labels would be evaluated. I can imagine code
like this:
bool is_0_or_1(int n)
{
int i = 0;
switch(n)
{
default:
return false;
case i++:
case i:
return true;
}
}
Choices: leave it unspecified which items are evaluated and in which
order. There's no need to support side-effects here; people just
want to be able to use known values that may not be compile-time
constants.
|
Unspecified? Come on, we already have too many unspecified things in C++.
IMO the best and most intuitive solution would be the short-circuit
evaluation. So only the labels that are "reached" during the search are
evaluated. That is:
int f(int i) { return i; } // returns argument
switch(x) {
case f(1):
// go below, also evaluating f(2)
case f(2):
// both f(1) and f(2) must have been called to get here
break; // jump out, f(3) not evaluated
case f(3):
// f(1), f(2) and f(3) must have been called to get here
break; // jump out
default:
// same as case f(3)
break;
} // switch
So far I think it's coherent and easy, and it doesn't break any existing
code (it only adds new possibilities). Does anybody find some weaknesses of
this approach? Or maybe someone has a better idea? If so, please write about
it.
| Quote: | Anyway, there is a perfectly elegant notation for the
general case:
const some_type &n = some_complicated_expression();
if (n == first_case) {
} else if (n == second_case) {
} else if (n == third_case) {
} else {
}
Duplication is inelegant, as is the use of excessively general
constructs for simple situations. When I see a switch statement,
I know at a glance that the code is testing one value against a
number of different possibilities. When I see an if/else ladder,
all I know is that there are a pile of different conditions being
tested.
|
I agree with you, I also think that.
Best regards,
Robert
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Laurie Cheers Guest
|
Posted: Thu Sep 30, 2004 5:13 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
[email]paul_evans7 (AT) hotmail (DOT) com[/email] (Paul Evans) wrote in message news:<4374f570.0409280914.7c4ec982 (AT) posting (DOT) google.com>...
| Quote: | James Dennett <jdennett (AT) acm (DOT) org> wrote
[snip]
It's a shame that C and C++ lack an elegant notation for
a more general switch/case construct,
[snip]
how about:
#include <iostream
#include
using namespace std;
void case1() { cout << "foo1" << endl; }
void case2() { cout << "foo2" << endl; }
void case3() { cout << "foo3" << endl; }
typedef void (*pfv)();
int main() {
map
dynamic_switch[4] = &case1;
dynamic_switch[6] = &case2;
dynamic_switch[9] = &case3;
int x = 6;
dynamic_switch[x]();
return 0;
}
|
Er...what?
The issue was that it's impossible to write a switch statement to compare
x with a value that's *not constant*.
Most people resort to an if-else chain for this, which is less concise and a
less clear way to express the programmer's intent.
The map approach loses the readability and conciseness (and probably the
efficiency) of a switch, without solving this problem!
--
Laurie Cheers
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Michiel Salters Guest
|
Posted: Fri Oct 01, 2004 4:59 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
[email]laurie.cheers (AT) btinternet (DOT) com[/email] (Laurie Cheers) wrote in message news:<c26006e0.0409300035.54d6cd65 (AT) posting (DOT) google.com>...
| Quote: | paul_evans7 (AT) hotmail (DOT) com (Paul Evans) wrote in message news:<4374f570.0409280914.7c4ec982 (AT) posting (DOT) google.com>...
James Dennett <jdennett (AT) acm (DOT) org> wrote
[snip]
It's a shame that C and C++ lack an elegant notation for
a more general switch/case construct,
[snip]
how about:
#include <iostream
#include
using namespace std;
void case1() { cout << "foo1" << endl; }
void case2() { cout << "foo2" << endl; }
void case3() { cout << "foo3" << endl; }
typedef void (*pfv)();
int main() {
map
dynamic_switch[4] = &case1;
dynamic_switch[6] = &case2;
dynamic_switch[9] = &case3;
int x = 6;
dynamic_switch[x]();
return 0;
}
Er...what?
The issue was that it's impossible to write a switch statement to compare
x with a value that's *not constant*.
|
Trivial change:
int main() {
map<boost::cref dynamic_switch;
int c1 = 4;
int c2 = 6;
int c3 = 9;
dynamic_switch[c1] = &case1;
dynamic_switch[c2] = &case2;
dynamic_switch[c3] = &case3;
int x = 6;
dynamic_switch[x]();
return 0;
}
Warning: don't change the values too much, or you won't find
it. You probably don't want to use std::map here, though.
dynamic_switch[6] is a silent noop, dynamic_switch[5]() crashes.
What you'd need is something like an encapsulated
std::vector<std::pair
with reasonable semantics - e.g. a setDefault(void(*)())
Of course, the main problem is that it really is impossible to
write such a switch. The essential part of the switch is that
a value matches exactly zero or one case, and that it is provable
when the case is built. Furthermore, all cases are equivalent.
An if..else if.. chain is fundamentally different. There can be
mmore than one matching "case" there and in case of multiple
matches the first matching 'if' is chosen.
The encapsulated vector< > will work the same way, the order in
which you called .addCase(T const*, void(*)()) will matter. The
wrapper can only guarantee there are no duplicate pointers.
Code like
int fooVal = 1;
int barVal = 2;
dynamicSwitch.addCase(&fooVal, &foo);
dynamicSwitch.addCase(&barVal, &bar);
fooVal = 2;
cannot be resolved in a way which mimicks the behavior of a
switch.
Regards,
Michiel Salters
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
John Nagle Guest
|
Posted: Fri Oct 01, 2004 5:00 pm Post subject: Re: Why must values in case labels be compile-time constants |
|
|
Francis Glassborow wrote:
| Quote: | In article <t5r6d.36683$aW5.9541@fed1read07>, James Dennett
[email]jdennett (AT) acm (DOT) org[/email]> writes
Hyman Rosen wrote:
James Dennett wrote:
|
You're reinventing Djkystra's guards here. Please
read his 1974 "A Discipline of Programming" for
his analysis of a symmetrical multiple-alternative
construct.
A C++ version of that might look like
unsigned n;
...
switch {
case n == 0: ... break;
case n == 1: ... break;
case n > 1 && n < 100: ... break;
default:
};
Djkystra suggests that when more than one alternative is true,
one should be randomly chosen. Never is more than one case
executed.
This concept is thirty years old and was not successful.
John Nagle
Animats
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Sat Oct 02, 2004 4:54 am Post subject: Re: Why must values in case labels be compile-time constants |
|
|
[email]jdennett (AT) acm (DOT) org[/email] (James Dennett) wrote (abridged):
| Quote: | Choices: leave it unspecified which items are evaluated and in which
order. There's no need to support side-effects here; people just
want to be able to use known values that may not be compile-time
constants.
|
They also want to use user-defined equality tests. For example, I'd like
to be able to use strings as case labels, with equality tests being done
like strcmp() rather than by comparing pointers.
One question is whether the compiler is allowed to evaluate case
expressions more than once, and if so, what happens if they return
different results. This is because a switch is often best implemented, not
as a linear search or a jump table, but as a binary search:
switch (x) {
case 1: return 1;
case 2: return 2;
case 49: return 9;
case 52: return 2;
case 101: return 1;
case 102: return 2;
case 149: return 9;
case 152: return 2;
default: return -1;
}
could become something like:
if (x <= 100)
if (x < 49)
return (x == 1) ? 1 : (x == 2) ? 2 : -1;
else
return (x == 49) ? 9 : (x == 52) ? 2 : -1;
else
if (x < 149)
return (x == 101) ? 1 : (x == 102) ? 2 : -1;
else
return (x == 149) ? 9 : (x == 152) ? 2 : -1;
Here I have evaluated some branch labels, eg 49, twice. I would an
extended switch() could do the same thing - could use operator<() as well
as operator==() even if all the numbers were strings. There is potential
for an infinite loop if operator<() does not define a total ordering, so
we probably need to allow undefined behaviour.
-- Dave Harris, Nottingham, UK
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|