C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Why must values in case labels be compile-time constants?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
Prateek R Karandikar
Guest





PostPosted: Tue Sep 21, 2004 6:37 pm    Post subject: Why must values in case labels be compile-time constants? Reply with quote



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





PostPosted: Tue Sep 21, 2004 8:18 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote



"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





PostPosted: Wed Sep 22, 2004 5:08 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote



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





PostPosted: Wed Sep 22, 2004 5:48 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

[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





PostPosted: Tue Sep 28, 2004 3:37 am    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

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





PostPosted: Tue Sep 28, 2004 3:42 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

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





PostPosted: Tue Sep 28, 2004 3:47 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

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





PostPosted: Tue Sep 28, 2004 10:15 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

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





PostPosted: Wed Sep 29, 2004 6:34 am    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

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





PostPosted: Wed Sep 29, 2004 5:38 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

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





PostPosted: Wed Sep 29, 2004 9:28 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

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





PostPosted: Thu Sep 30, 2004 5:13 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

[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





PostPosted: Fri Oct 01, 2004 4:59 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

[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





PostPosted: Fri Oct 01, 2004 5:00 pm    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

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





PostPosted: Sat Oct 02, 2004 4:54 am    Post subject: Re: Why must values in case labels be compile-time constants Reply with quote

[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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.