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

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

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


当前回答

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

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

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

其他回答

在c++中,你只能在int和char上使用switch语句

如前所述,编译器喜欢构建查找表,尽可能地将switch语句优化到接近O(1)的时间。再加上c++语言没有字符串类型——std::string是标准库的一部分,而标准库本身不是语言的一部分。

我将提供一个你可能想要考虑的替代方案,我过去用过它,效果很好。不是切换字符串本身,而是切换使用字符串作为输入的哈希函数的结果。如果你使用一组预先确定的字符串,你的代码几乎和切换字符串一样清晰:

enum string_code {
    eFred,
    eBarney,
    eWilma,
    eBetty,
    ...
};

string_code hashit (std::string const& inString) {
    if (inString == "Fred") return eFred;
    if (inString == "Barney") return eBarney;
    ...
}

void foo() {
    switch (hashit(stringValue)) {
    case eFred:
        ...
    case eBarney:
        ...
    }
}

这里有一堆明显的优化,基本上遵循了C编译器对switch语句的处理……真有趣。

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

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++和C语言中,开关只适用于整型。使用if else梯子代替。c++显然可以为字符串实现某种switch语句——我猜没有人认为值得这样做,我同意他们的观点。

开关问题的更实用的解决方案:

class APIHandlerImpl
{

// define map of "cases"
std::map<string, std::function<void(server*, websocketpp::connection_hdl, string)>> in_events;

public:
    APIHandlerImpl()
    {
        // bind handler method in constructor
        in_events["/hello"] = std::bind(&APIHandlerImpl::handleHello, this, _1, _2, _3);
        in_events["/bye"] = std::bind(&APIHandlerImpl::handleBye, this, _1, _2, _3);
    }

    void onEvent(string event = "/hello", string data = "{}")
    {
        // execute event based on incomming event
        in_events[event](s, hdl, data);
    }

    void APIHandlerImpl::handleHello(server* s, websocketpp::connection_hdl hdl, string data)
    {
        // ...
    }

    void APIHandlerImpl::handleBye(server* s, websocketpp::connection_hdl hdl, string data)
    {
        // ...
    }
}