由于我们不能直接在switch-case语句中使用字符串,因为它们无法计算常量,因此我将条目映射到map<string,int>
。
map<string,int> hash;
hash["+x"] = 0;
hash["-x"] = 1;
hash["+y"] = 2;
hash["-y"] = 3;
hash["+z"] = 4;
hash["-z"] = 5;
现在,我在switch-case表达式中使用它们:
cin >> bend //assume user entered +x
switch(hash[bend])
{
case hash["+y"] :
switch(pointedto)
{
case hash["+x"]: pointedto = hash["+y"];
break;
case hash["-x"]: pointedto = hash["-y"];
break;
case hash["+y"]: pointedto = hash["-x"];
break;
case hash["-y"]: pointedto = hash["+x"];
break;
case hash["+z"]: pointedto = hash["+z"];
break;
case hash["-z"]: pointedto = hash["-z"];
break;
}
}
我收到错误:
所有an array reference cannot appear in a constant-expression
的{{1}}。我期待case
和其他人返回hash["+x"]
,这将导致一个常量。
PS:另一种选择是来自int
的{{1}},但我很想使用这个。
答案 0 :(得分:4)
此特定代码示例中的问题是case
值应该是编译时常量。 std::map::operator[]
返回的值不是,因此不能在case
子句中使用。
您可以使用基于constexpr
的方法,如下所示:
constexpr array<double, 10> values = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
constexpr int f(double f) {
for (int i = 0; i < 10; ++i) {
if (values[i] == f) {
return i;
}
}
return -1;
}
double x = 4.0;
switch (f(x)) {
case f(1.0) :
break;
case f(2.0) :
break;
...
default :
break;
}
但它仅适用于constexpr
- 可构造类型。不幸的是,std::string
不是其中之一。
答案 1 :(得分:3)
不要与语言作斗争。
C ++ switch
语句中的案例标签需要编译时可评估的常量表达式,而C ++标准库std::map
或std::unordered_map
则不目前提供。
改为使用if
else
块。它甚至可能会更快 - 特别是如果您选择最佳订单。
switch
字符数组(例如'+x'
;请注意单引号字符)经常作为4个字符或更少字符的替代品,但即便如此不便携。
答案 2 :(得分:1)
一些解决方案:
尽早摆脱字符串。声明enum direction {posX, negX, posY, negY, posZ, negZ}
并声明pointedto
为direction
类型而不是字符串。现在你可以说case posY:
是编译时常量,但比case 2:
更具可读性。将hash
更改为map<string, direction>
以解析用户的输入,使用direction
执行所有处理,并定义map<direction, string>
以在您想要呈现时转换回字符串回答用户。
认识到搜索地图“有点像”一个开关。包含嵌套开关的开关可以通过映射图(map<direction, map<direction, direction>>
)进行模拟,以便所有开关可以用一行替换:pointedto = hash[bend][pointedto];
或嵌套开关可以用一个带有“复合键”(map<pair<direction, direction>, direction>
)的地图替换,以便所有开关都被pointedto = hash[make_pair(bend, pointedto)];
替换。这将与bend
和pointedto
一起用作字符串 - 所以hash["+y"]["+x"] == "+y"
- 但如果您在用户输入和输出之间进行了多次迭代,则枚举可能会更有效。
使用巧妙选择的值声明一个枚举,例如enum direction {posX=4, negX=0, posY=5, negY=1, posZ=6, negZ=2}
,并找到一些聪明的数学来转换弯曲并指向一个新的指向值。 注意:我在此处说明的值仅用于说明目的 - 只有在您真正需要针对性能优化此代码时才应使用此路由。为了完整起见,我提到了这条路线,但如果您决定使用它,则对不眠之夜不承担任何责任:)
修改强>
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
enum direction {posX, negX, posY, negY, posZ, negZ};
const direction transform[6][6]{
// previous pointed to: bend
// +x -x +y -y +z -z ----
{ }, // +x
{ }, // -x
{ posY, negY, negX, posX, posZ, negZ}, // +y
{ }, // -y
{ }, // +z
{ }, // -z
};
const std::map<std::string, direction> stringToDirection{ { "+x", posX },{ "-x", negX },{ "+y", posY },{ "-y", negY },{ "+z", posZ },{ "-z", negZ } };
const std::map<direction, std::string> directionToString{ { posX, "+x" },{ negX, "-x" },{ posY, "+y" },{ negY, "-y" },{ posZ, "+z" },{ negZ, "-z" } };
int main(int, char**) {
direction pointedto = posY;
std::string bendInput;
std::cin >> bendInput;
direction bend = stringToDirection.at(bendInput);
pointedto = transform[bend][pointedto];
std::cout << directionToString.at(pointedto) << "\n";
return 0;
}
注意:
directionToString
应该来自stringToDirection
,但我想在这里保持简单。