我在很多地方都有以下模式:
unsigned key = getKey();
auto res = [=]() {
switch (key)
{
case 12: return &x;
case 14: return &y;
case 81: return &z;
default: fatal_error();
}
}();
它是从非连续整数(通常是枚举)到其他一些值(通常是函数指针)的映射。开关结构适用于此但包含大量线路噪声。可以通过分配给变量来替换立即调用的lambda,以换取大量break;
语句。
写这个的干净,规范的方法是什么?对于连续的整数,它可以是:
std::array<ptr_t, 3> map = {{&x, &y, &z}};
auto res = map[key];
一种选择是使用地图(有序或无序),
std::map<unsigned, ptr_t> map = {{12, &x}, {14, &y}, {81, &z}};
auto res = map[key];
在代码清晰度方面哪个好,但相对不太可能被编译器剥离,因为映射涉及树和一堆堆分配。
另一个是通过哈希函数
std::array<ptr_t, 4> map = {{&y, &z, nullptr, &x}};
auto res = map[hash(key)]; // don't want to write hash() each time
我不介意,只要不涉及堆,调度是通过近乎完美的散列函数进入数组还是通过分支。可以改进上述开关吗?
来自nwp的建议:
using kvp_t = std::pair<unsigned, ptr_t>;
std::array<kvp_t, 3> m = {{
{12, &x}, {14, &y}, {81, &z},
}};
auto res = std::find_if(m.begin(),m.end(),[=](kvp_t k) {
return k.first == key;
})->second;