3

C++ 中的 switch 语句必须用常量编写这一事实背后的原因是什么?

我们来看看下面的代码:

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;
}

在其他语言中,例如 PAWN(C-Like 脚本语言),我可以这样写下这段代码:

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

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

    default:
        //Code 3
        break;
}

C++ switch 语句从石器时代开始的事实背后的原因是什么?(更不用说我们不能使用变量。)

即使这些年来经历了如此多的变化和更新......

4

3 回答 3

5

没有技术原因不能更新 C 的 switch 语句以使用范围。gcc 已经对此进行了扩展。

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

值保持不变是有充分理由的;允许进行各种优化,例如跳转表。

于 2013-05-07T00:36:21.123 回答
1

如果您不介意再次查找,您可以生成一个表来简化您的案例陈述:

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;
}

或者,您可以创建一个unordered_map函数指针或方法,其中键是您的variable类型。

于 2013-05-07T01:12:49.683 回答
1

switch和 Pascal 一样,它是为简单的表查找而设计的case。帕斯卡case支持的范围,我记得,与帕斯卡位集相同的符号。C 也可以这样做,但无论出于何种原因,都没有。

并且对该功能的需求不足以使其成为标准、C 或 C++。

关于案例标签的变量或非整数类型,这将改变语句的性质。C 和 C++ 根本没有一般性陈述select。但是在 C++ 中,你可以自己做:

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;
}

然后你可以写像

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"; } }
    } );
}

如果需要,您可以轻松地为其添加默认值,例如使用or关键字。

嗯,有趣的是我以前没有想到这一点,但显然其他人也没有。:)

于 2015-04-26T11:06:20.240 回答