编译下面的代码会得到错误消息: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中使用字符串。为什么?是否有任何解决方案可以很好地支持类似于打开字符串的逻辑?
当前回答
你不能在开关情况下使用字符串。只允许int和char类型。相反,您可以尝试用enum表示字符串,并在switch case块中使用它
enum MyString(raj,taj,aaj);
在switch case语句中使用它。
其他回答
std::map + c++ 11没有枚举的lambdas模式
潜在的平摊O(1)的unordered_map:在c++中使用HashMap的最佳方式是什么?
#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
int main() {
int result;
const std::unordered_map<std::string,std::function<void()>> m{
{"one", [&](){ result = 1; }},
{"two", [&](){ result = 2; }},
{"three", [&](){ result = 3; }},
};
const auto end = m.end();
std::vector<std::string> strings{"one", "two", "three", "foobar"};
for (const auto& s : strings) {
auto it = m.find(s);
if (it != end) {
it->second();
} else {
result = -1;
}
std::cout << s << " " << result << std::endl;
}
}
输出:
one 1
two 2
three 3
foobar -1
在静态方法中使用
要在类中有效地使用这种模式,可以静态地初始化lambda映射,否则每次从头构建时都要付出O(n)。
在这里,我们可以摆脱静态方法变量的{}初始化:类方法中的静态变量,但我们也可以使用在:c++中的静态构造函数?我需要初始化私有静态对象
必须将lambda上下文捕获[&]转换为参数,否则将未定义:const static auto lambda与capture by reference一起使用
示例,产生与上面相同的输出:
#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
class RangeSwitch {
public:
void method(std::string key, int &result) {
static const std::unordered_map<std::string,std::function<void(int&)>> m{
{"one", [](int& result){ result = 1; }},
{"two", [](int& result){ result = 2; }},
{"three", [](int& result){ result = 3; }},
};
static const auto end = m.end();
auto it = m.find(key);
if (it != end) {
it->second(result);
} else {
result = -1;
}
}
};
int main() {
RangeSwitch rangeSwitch;
int result;
std::vector<std::string> strings{"one", "two", "three", "foobar"};
for (const auto& s : strings) {
rangeSwitch.method(s, result);
std::cout << s << " " << result << std::endl;
}
}
问题是,由于优化的原因,c++中的switch语句只能用于基本类型,你只能将它们与编译时常量进行比较。
这种限制的原因可能是编译器能够应用某种形式的优化,将代码编译为一个cmp指令和一个goto,其中地址是根据运行时参数的值计算的。由于分支和循环在现代cpu上不能很好地发挥作用,因此这可能是一个重要的优化。
要解决这个问题,恐怕你将不得不求助于if语句。
hare对Nick解决方案的评论真的很酷。这里是完整的代码示例(c++ 11):
constexpr uint32_t hash(const std::string& s) noexcept
{
uint32_t hash = 5381;
for (const auto& c : s)
hash = ((hash << 5) + hash) + (unsigned char)c;
return hash;
}
constexpr inline uint32_t operator"" _(char const* p, size_t) { return hash(p); }
std::string s = "raj";
switch (hash(s)) {
case "sda"_:
// do_something();
break;
default:
break;
}
你不能在开关情况下使用字符串。只允许int和char类型。相反,您可以尝试用enum表示字符串,并在switch case块中使用它
enum MyString(raj,taj,aaj);
在switch case语句中使用它。
在c++中,字符串不是一等公民。字符串操作是通过标准库完成的。我想,这就是原因。另外,c++使用分支表优化来优化开关case语句。看看这个链接。
http://en.wikipedia.org/wiki/Switch_statement