C++ 错误:开关数量不是整数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4535825/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:40:36  来源:igfitidea点击:

error: switch quantity not an integer

c++stringswitch-statementconstant-expression

提问by Ken

I have researched my issue all over StackOverflow and multi-google links, and I am still confused. I figured the best thing for me is ask...

我已经通过 StackOverflow 和多谷歌链接研究了我的问题,但我仍然感到困惑。我想对我来说最好的事情是问...

Im creating a simple command line calculator. Here is my code so far:

我正在创建一个简单的命令行计算器。到目前为止,这是我的代码:

const std::string Calculator::SIN("sin");  
const std::string Calculator::COS("cos");  
const std::string Calculator::TAN("tan");  
const std::string Calculator::LOG( "log" );  
const std::string Calculator::LOG10( "log10" );

void Calculator::set_command( std::string cmd ) {

    for(unsigned i = 0; i < cmd.length(); i++)
    {
    cmd[i] = tolower(cmd[i]);
    }

    command = cmd;
}

bool Calculator::is_legal_command() const {

    switch(command)
    {
    case TAN:
    case SIN:
    case COS:
    case LOG:
    case LOG10:
        return true;
        break;
    default:
        return false;
        break;
    }

}

the error i get is:

我得到的错误是:

Calculator.cpp: In member function 'bool Calculator::is_trig_command() const':  
Calculator.cpp: error: switch quantity not an integer  
Calculator.cpp: error: 'Calculator::TAN' cannot appear in a constant-expression  
Calculator.cpp: error: 'Calculator::SIN' cannot appear in a constant-expression  
Calculator.cpp: error: 'Calculator::COS' cannot appear in a constant-expression  

The mighty internet, it says strings are allowed to be used in switch statements.

强大的互联网,它说允许在 switch 语句中使用字符串。

Thanks everyone, I appreciate your help.

谢谢大家,我感谢你的帮助。

回答by DVK

In switch, the expression must be of "an integral typeor of a class type for which there is an unambiguous conversion to integral type" (quoting VS2008 docs).

在 中switch,表达式必须是“一个整数类型或一个可以明确转换为整数类型的类类型”(引用 VS2008 文档)。

A string class doesn't have "unambiguous conversion to integral type", like a chardoes.

字符串类不像 a 那样具有“明确转换为整数类型” char

As a work-around:

作为解决方法:

  1. Create a map<string, int>and switch on the value of the map: switch(command_map[command])`

  2. Do a set of if/elseinstead of switch. Much more annoying and hard to read, so I'd recommend the map route.

  1. 创建一个map<string, int>并打开地图的值:switch(command_map[command])`

  2. 做一组if/else而不是 switch。更烦人且难以阅读,所以我推荐地图路线。

As an aside, an even better solution for really complicated logic like that is to improve the mapping solution to get rid of switchcompletely and instead go with a function lookup: std::map<std::string, functionPointerType>. It may not be needed for your specific case, but is MUCH faster for complicated very long look-up logic.

顺便说一句,对于真正复杂的逻辑,一个更好的解决方案是改进映射解决方案以switch完全摆脱,而是使用函数查找:std::map<std::string, functionPointerType>. 对于您的特定情况可能不需要它,但对于复杂的超长查找逻辑要快得多。

回答by Johannes Schaub - litb

As others and the compiler commented, strings are not allowed with switch. I would just use if

正如其他人和编译器所评论的那样,字符串不允许使用switch. 我只会用if

bool Calculator::is_legal_command() const {
    if(command == TAN) return true;
    if(command == SIN) return true;
    if(command == COS) return true;
    if(command == LOG) return true;
    if(command == LOG10) return true;
    return false;
}

I don't think that's any more complicated, and it's about as fast as it could get. You could also use my switch macro, making it look like

我不认为这更复杂,而且速度很快。你也可以使用我的switch 宏,让它看起来像

bool Calculator::is_legal_command() const {
    sswitch(command)
    {
    scase (TAN):
    scase (SIN):
    scase (COS):
    scase (LOG):
    scase (LOG10):
        return true;

    sdefault():
        return false;
    }
}

(having breakafter a returnis dead code, and so should be avoided).

break在 a 之后return是死代码,因此应该避免)。

回答by Martin York

Rather than a switch.

而不是一个开关。

I would use a command pattern. Then use a std::map to map the function name to the command object.

我会使用命令模式。然后使用 std::map 将函数名称映射到命令对象。

Something like this:

像这样的东西:

#include <math.h>
#include <map>
#include <string>
#include <iostream>

class Function
{
    public:
        // Easy public API that just uses the normal function call symantics
        double   operator()(double value)   { return this->doWork(value);}
        virtual ~Function()     {}
    private:
        // Virtual function where the work is done.
        virtual double doWork(double value) = 0;
};

// A sin/cos function
class Sin: public Function      { virtual double doWork(double value)     { return sin(value); } };
class Cos: public Function      { virtual double doWork(double value)     { return cos(value); } };

// A class that holds all the functions.
// A function name is mapped to a function object.
class FuncMap
{
    public:
        FuncMap()
        {
            // Constructor sets up the map
            functions["sin"]    = &sinFunc;
            functions["cos"]    = &cosFunc;
        }
        Function*   getFunction(std::string command) const
        { 
            // Default result not found.
            Function* result    = NULL;
            std::map<std::string, Function*>::const_iterator    find;

            // Look in the map to see if we find the value.
            // If it exists then find will not point at end()
            if ((find = functions.find(command)) != functions.end())
            {
                // Get the pointer to the function
                result  = find->second;
            }
            return result;
        }
    private:
    Sin     sinFunc;
    Cos     cosFunc;

    std::map<std::string, Function*>    functions;
};

// Declaring it globally for ease of use.
FuncMap     functions;


int main()
{
    // SImple example of usage.
    Function*   func    = functions.getFunction("sin");
    if (func == NULL)
    {
        std::cout << "No Function sin()\n";
        exit(1);
    }
    std::cout << "Result: " << (*func)(12.34) << "\n";
}

回答by SoapBox

Strings cannot be used in switch statements in C++. You'll need to turn this into if/else if, like this:

字符串不能在 C++ 的 switch 语句中使用。你需要把它变成if/ else if,像这样:

if (command == "tan")
{
    // ...
}
else if (command == "cos")
{
    // ...
}
// ...

回答by Adam Maras

Not sure which mighty Internet you've been reading, but C++ doesn't allow strings in switchstatements. (C# does, though.)

不确定您读过哪个强大的 Internet,但 C++ 不允许在switch语句中使用字符串。(不过,C# 确实如此。)

You need to convert your switchstatement to a chain of if-else if-elsestatements that test equality.

您需要将转换switch语句链if- else if-else语句测试平等。

回答by Lightness Races in Orbit

The compiler error tells you everything you need to know. Only integral types may be compared in switch statements.

编译器错误告诉您需要知道的一切。在 switch 语句中只能比较整数类型。

I'm not sure which "mighty internet" told you otherwise, but it was mighty wrong.

我不确定哪个“强大的互联网”告诉你否则,但这是大错特错。

回答by villintehaspam

Strings cannot be used as constants in switch statements in c++. You can either use a map, a series of if's or you can move from representing your commands as strings to an enum. Parse from string to enum once, then use a switch like you do now. Note that your string parsing may require the same mechanism (map/if's), but depending on your use case using one approach over the other may improve readability. I'm not going to say anything on which approach is more readable.

字符串不能用作 C++ 中 switch 语句中的常量。您可以使用映射、一系列 if,也可以从将命令表示为字符串转移到枚举。从字符串解析为枚举一次,然后像现在一样使用开关。请注意,您的字符串解析可能需要相同的机制(map/if),但根据您的用例,使用一种方法而不是另一种方法可能会提高可读性。我不会说哪种方法更具可读性。