【问题标题】:Why do case statements only accept constants?为什么 case 语句只接受常量?
【发布时间】:2013-05-07 00:26:18
【问题描述】:

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 语句是从石器时代开始的,背后的原因是什么? (更不用说我们不能使用变量。)

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

【问题讨论】:

  • 运行时很难创建跳转表?范围的事情是一种单独的交易。或许如果该语法曾经出现过(我个人觉得它有点好;它也在 D 中),那么不久之后将其添加到开关的提议不会太久,但它可能需要一些额外的工作才能保持一致switch 语法。
  • PAWN 语法与强制常量有什么关系? 1 .. 4 不是常数吗? (另外,制作一个宏SEQ(1, 4)
  • @Pubby,有趣的想法。我不太喜欢预处理器黑魔法,但BOOST_PP_FOR 可以做到吗?
  • 这是语言的定义方式。
  • @NemanjaTrifunovic:这个问题是关于另一个问题的。

标签: c++ c++11 switch-statement


【解决方案1】:

C switch 语句无法更新为使用范围没有技术原因。 gcc 已经对此进行了扩展。

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

值保持恒定是有充分理由的;这允许各种优化,例如跳转表。

【讨论】:

    【解决方案2】:

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

    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 类型。

    【讨论】:

      【解决方案3】:

      switch 设计用于简单的表查找,Pascal case 也是如此。 Pascal case 支持的范围,我记得使用与 Pascal 位集相同的表示法。 C 也可以这样做,但无论出于何种原因,都没有。

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

      关于 case 标签的变量或非整数类型,这将改变语句的性质。 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 关键字。

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

      【讨论】:

        猜你喜欢
        • 2010-09-24
        • 2014-02-24
        • 1970-01-01
        • 2016-03-25
        • 1970-01-01
        • 1970-01-01
        • 2011-07-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多