user1182183
user1182183

Reputation:

Why do case statements only accept constants?

What is the reason behind the fact thet switch statements in C++ have to be written with constants?

Let's take a look at the following code:

switch(variable)
{
    case 1:
    case 2:
    case 3:
    case 4:
        //Code 1
        break;

    case 5:
    case 6:
    case 7:
    case 8:
        //Code 2
        break;

    default:
        //Code 3
        break;
}

In other languages, for example PAWN (C-Like scripting language), I could write this code down as such:

switch(variable)
{
    case 1 .. 4:
        //Code 1
        break;

    case 5 .. 8:
        //Code 2
        break;

    default:
        //Code 3
        break;
}

What is the reason behind the fact the C++ switch statement is soo.. from the Stone Age? (Not to mention we can't use variables.)

Even after so many changes and updates over all those years...

Upvotes: 3

Views: 230

Answers (3)

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145359

The switch was designed for a simple table-lookup, as was the Pascal case. The Pascal case supported ranges, with, as I recall, the same notation as for Pascal bitsets. C could have done likewise, but for whatever reasons, didn't.

And there's just not been sufficient demand for that feature to make it into either standard, C or C++.

Regarding variables or non-integral types for the case labels, that would change the nature of the statement. C and C++ simply do not have a general select statement. But in C++ you can cook it up yourself:

template< class Key >
auto select(
    const Key&                          key,
    const map<Key, function<void()>>&   actions
    )
    -> bool
{
    const auto it = actions.find( key );
    if( it == actions.end() ) { return false; }
    it->second();  return true;
}

And then you can write things like

auto main() -> int
{
    cout << "Command? ";
    const string command = readline();
    select( command, map<string, function<void()>>
    {
        { "blah", []{ cout << "You said blah!\n"; } },
        { "asd",  []{ cout << "You said asd!?!\n"; } }
    } );
}

You can easily add a default to that if you want, e.g. by using the or keyword.

Hm, funny I didn't think of that before, but then apparently neither did anyone else. :)

Upvotes: 1

jxh
jxh

Reputation: 70472

If you don't mind another lookup, you could generate a table to simplify your case statement:

char the_case (unsigned variable) {
    static const char all_cases[] = {
        0,
        'A', 'A', 'A', 'A',
        'B', 'B', 'B', 'B',
    };
    if (variable < sizeof(all_cases)) return all_cases[variable];
    return 0;
}

//...
switch (the_case(variable)) {
case 'A':
    //...
    break;
case 'B':
    //...
    break;
default:
    //...
    break;
}

Alternatively, you can create an unordered_map to function pointers or methods, where the key is your variable type.

Upvotes: 1

StilesCrisis
StilesCrisis

Reputation: 16290

There's no technical reason that C switch statements couldn't be updated to use ranges. gcc already has an extension for this.

http://www.n4express.com/blog/?p=1225

There are good reasons for the values to be constant; that allows for all sorts of optimizations such as jump tables.

Upvotes: 5

Related Questions