【发布时间】:2015-10-27 17:07:13
【问题描述】:
我有一个枚举列表,定义如下:
enum PinEnum {
kPinInvalid,
kPinA0,
kPinA1,
kPinB0,
kPinB1,
kPinC0,
kPinC1,
}
这些枚举中的每一个都需要与另外两个值相关联,即端口和引脚号。目前,我正在通过运行时函数访问这些:
GPIO_TypeDef * PinGetPort(const PinEnum pin) {
switch (pin) {
case kPinA0:
case kPinA1:
return GPIOA;
case kPinB0:
case kPinB1:
return GPIOB;
case kPinC0:
case kPinC1:
return GPIOC;
default:
return NULL;
}
}
uint16_t PinGetPin(const PinEnum pin) {
switch (pin) {
case kPinA0:
case kPinB0:
case kPinC0:
return GPIO_Pin_0;
case kPinA1:
case kPinB1:
case kPinC1:
return GPIO_Pin_1;
default:
return 0;
}
}
特别是,我这样做是因为我不希望大型查找表在运行时占用 RAM(代码大小不是问题)。
有没有办法使用编译时查找表、constexpr 函数或模板构造来做到这一点,以便语句 PinGetPin(kPinA0) 和 PinGetPort(kPinA0) 每个都优化为单个值而不是必须经历冗长的函数调用和案例语句?这些函数的参数将始终为 const PinEnum 类型,其值在编译时已知。
例如,一个典型的使用场景如下:
const PinEnum kPinStatus = kPinB0;
int main(int argc, char ** argv) {
...
PinGetPort(kPinStatus)->BSRRH = PinGetPin(kPinStatus);
// GPIOB->BSRRH = GPIO_Pin_0; <-- should optimize to this during compilation
...
}
C++11 答案很好。
虽然对于编译时查找表还有其他答案,但我没有看到直接适用于这种情况的答案。它们要么需要字符串递归,要么实际计算并存储一个查找表(如果没有其他方法,这最终可能会出现)。
【问题讨论】:
-
“它们要么需要字符串递归,要么实际计算并存储一个查找表(如果没有其他方法,这最终可能会出现)。” ....这就是为什么这是重复的。这个已经被问过了。答案不是你所希望的这一事实并不能改变它们是最好的答案这一事实,正如你刚刚承认的那样!
-
@LightnessRacesinOrbit “我想在没有字符串递归或存储(在数据中)查找表的情况下执行 X,如何?”是一个不同的问题,“我想做 X,怎么做?”因为第二个的答案并不总是回答第一个。 ;)
-
@Yakk 我大体上同意,但是当 50,000 个答案已经说过“这样做的唯一方法是使用字符串递归或存储(在数据中)查找表”时,我不认为我们需要关于该主题的另一个问题。 :)