编译下面的代码会得到错误消息:type illegal。
int main()
{
// Compilation error - switch expression of type illegal
switch(std::string("raj"))
{
case"sda":
}
}
你不能在switch或case中使用字符串。为什么?是否有任何解决方案可以很好地支持类似于打开字符串的逻辑?
编译下面的代码会得到错误消息:type illegal。
int main()
{
// Compilation error - switch expression of type illegal
switch(std::string("raj"))
{
case"sda":
}
}
你不能在switch或case中使用字符串。为什么?是否有任何解决方案可以很好地支持类似于打开字符串的逻辑?
当前回答
原因与类型系统有关。C/ c++并不真正支持字符串作为类型。它确实支持常量字符数组的概念,但它并没有真正完全理解字符串的概念。
为了生成switch语句的代码,编译器必须理解两个值相等意味着什么。对于int和enum这样的项,这是一个微不足道的比特比较。但是编译器应该如何比较2个字符串值呢?区分大小写,不敏感,文化意识等等……如果没有对弦的充分认识,就不能准确地回答这个问题。
此外,C/ c++ switch语句通常生成为分支表。为字符串样式切换生成分支表远没有那么容易。
其他回答
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]);
}
问题是,由于优化的原因,c++中的switch语句只能用于基本类型,你只能将它们与编译时常量进行比较。
这种限制的原因可能是编译器能够应用某种形式的优化,将代码编译为一个cmp指令和一个goto,其中地址是根据运行时参数的值计算的。由于分支和循环在现代cpu上不能很好地发挥作用,因此这可能是一个重要的优化。
要解决这个问题,恐怕你将不得不求助于if语句。
C++
Constexpr哈希函数:
constexpr unsigned int hash(const char *s, int off = 0) {
return !s[off] ? 5381 : (hash(s, off+1)*33) ^ s[off];
}
switch( hash(str) ){
case hash("one") : // do something
case hash("two") : // do something
}
更新:
上面的例子是c++ 11。这里的constexpr函数必须是单语句。这在接下来的c++版本中得到了放宽。
在c++ 14和c++ 17中,你可以使用以下哈希函数:
constexpr uint32_t hash(const char* data, size_t const size) noexcept{
uint32_t hash = 5381;
for(const char *c = data; c < data + size; ++c)
hash = ((hash << 5) + hash) + (unsigned char) *c;
return hash;
}
c++ 17也有std::string_view,所以你可以用它来代替const char *。
在c++ 20中,您可以尝试使用consteval。
我认为原因是在C语言中字符串不是基本类型,就像tomjen说的,把字符串看作一个char数组,所以你不能做这样的事情:
switch (char[]) { // ...
switch (int[]) { // ...
你不能在开关情况下使用字符串。只允许int和char类型。相反,您可以尝试用enum表示字符串,并在switch case块中使用它
enum MyString(raj,taj,aaj);
在switch case语句中使用它。