编译下面的代码会得到错误消息:type illegal。

int main()
{
    // Compilation error - switch expression of type illegal
    switch(std::string("raj"))
    {
    case"sda":
    }
}

你不能在switch或case中使用字符串。为什么?是否有任何解决方案可以很好地支持类似于打开字符串的逻辑?


当前回答

这是因为c++将开关转换为跳转表。它对输入数据执行简单的操作,并在不进行比较的情况下跳转到适当的地址。因为字符串不是一个数字,而是一个数字数组,所以c++不能从它创建一个跳转表。

movf    INDEX,W     ; move the index value into the W (working) register from memory
addwf   PCL,F       ; add it to the program counter. each PIC instruction is one byte
                    ; so there is no need to perform any multiplication. 
                    ; Most architectures will transform the index in some way before 
                    ; adding it to the program counter

table                   ; the branch table begins here with this label
    goto    index_zero  ; each of these goto instructions is an unconditional branch
    goto    index_one   ; of code
    goto    index_two
    goto    index_three

index_zero
    ; code is added here to perform whatever action is required when INDEX = zero
    return

index_one
...

(代码来自维基百科https://en.wikipedia.org/wiki/Branch_table)

其他回答

你可以使用开关字符串。 你需要的是字符串表,检查每一个字符串

char** strings[4] = {"Banana", "Watermelon", "Apple", "Orange"};

unsigned get_case_string(char* str, char** _strings, unsigned n)
{
    while(n)
    {
        n--
        if(strcmp(str, _strings[n]) == 0) return n;
    }
    return 0;
}

unsigned index = get_case_string("Banana", strings, 4);

switch(index)
{
    case 1: break;/*Found string `Banana`*/
    default: /*No string*/
}

c++ 11的更新显然不是上面的@MarmouCorp,而是http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4067/Switch-on-Strings-in-C.htm

使用两个映射在字符串和类enum之间进行转换(比普通enum更好,因为它的值是在它内部的范围内,并且反向查找可以获得良好的错误消息)。

在codeguru代码中使用静态是可能的,因为编译器支持初始化列表,这意味着VS 2013 plus。GCC 4.8.1是可以的,不确定它能兼容多远的时间。

/// <summary>
/// Enum for String values we want to switch on
/// </summary>
enum class TestType
{
    SetType,
    GetType
};

/// <summary>
/// Map from strings to enum values
/// </summary>
std::map<std::string, TestType> MnCTest::s_mapStringToTestType =
{
    { "setType", TestType::SetType },
    { "getType", TestType::GetType }
};

/// <summary>
/// Map from enum values to strings
/// </summary>
std::map<TestType, std::string> MnCTest::s_mapTestTypeToString
{
    {TestType::SetType, "setType"}, 
    {TestType::GetType, "getType"}, 
};

...

std::string someString = "setType";
TestType testType = s_mapStringToTestType[someString];
switch (testType)
{
    case TestType::SetType:
        break;

    case TestType::GetType:
        break;

    default:
        LogError("Unknown TestType ", s_mapTestTypeToString[testType]);
}

这是我前段时间提出的一个解决方案,它完全遵守所请求的语法。

#include <uberswitch/uberswitch.hpp>

int main()
{
    uswitch (std::string("raj"))
    {
        ucase ("sda"): /* ... */ break;  //notice the parenthesis around the value.
    }
}

代码如下:https://github.com/falemagn/uberswitch

你不能在开关情况下使用字符串。只允许int和char类型。相反,您可以尝试用enum表示字符串,并在switch case块中使用它

enum MyString(raj,taj,aaj);

在switch case语句中使用它。

问题是,由于优化的原因,c++中的switch语句只能用于基本类型,你只能将它们与编译时常量进行比较。

这种限制的原因可能是编译器能够应用某种形式的优化,将代码编译为一个cmp指令和一个goto,其中地址是根据运行时参数的值计算的。由于分支和循环在现代cpu上不能很好地发挥作用,因此这可能是一个重要的优化。

要解决这个问题,恐怕你将不得不求助于if语句。