Why do case statements only accept constants?

家住魔仙堡 提交于 2020-01-03 19:31:22

问题


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...


回答1:


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.




回答2:


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.




回答3:


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. :)



来源:https://stackoverflow.com/questions/16409351/why-do-case-statements-only-accept-constants

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!