枚举的编译时查找表 [英] Compile-time lookup table for enum

查看:63
本文介绍了枚举的编译时查找表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个枚举列表,定义如下:

I have a list of enums which are defined as follows:

enum PinEnum {
    kPinInvalid,
    kPinA0,
    kPinA1,
    kPinB0,
    kPinB1,
    kPinC0,
    kPinC1,
}

这些枚举中的每个枚举都需要与其他两个值(端口和引脚号)相关联.目前,我正在通过运行时函数来访问这些文件:

Each of these enums needs to be associated with two other values, the port and the pin number. Currently, I'm accessing these through run-time functions:

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(代码大小已不再是问题).

In particular, I'm doing this because I do not want a large lookup table to be taking up RAM at runtime (code size is much less of an issue).

是否可以使用编译时查找表, constexpr 函数或模板构造来执行此操作,从而使语句 PinGetPin(kPinA0) PinGetPort(kPinA0)分别优化为单个值,而不必经历冗长的函数调用和case语句?这些函数的参数将始终为 const PinEnum 类型,其值在编译时为已知.

Is there a way to do this using a compile-time lookup table, constexpr function, or a template construct so that the statements PinGetPin(kPinA0) and PinGetPort(kPinA0) each get optimized to a single value instead of having to go through a lengthy function call and case statement? The arguments to these functions will always be of type const PinEnum with values known at compile time.

例如,以下是典型的使用场景:

For example, a typical usage scenario is the following:

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的答案很好.

C++11 answers are fine.

尽管对于编译时查找表还有其他答案,但我没有看到一个直接适用于这种情况的答案.它们要么需要字符串递归,要么实际上是计算并存储查找表(如果没有其他方法,最终可能会找到该表).

While there are other answers out there for compile-time lookup tables, I do not see one which would directly apply to this case. They either require string recursion, or actually calculate and store a lookup table (which this may end up coming to if there's no other way).

推荐答案

使用以枚举为参数的模板结构,模板专业化 std :: integral_constant .

Use template structs taking enum as a parameter, template specialization, and std::integral_constant.

#include <type_traits>

enum class pin { pin0, pin1 };

template<pin> struct lookup_port;    
template<pin> struct lookup_num;

template<> struct lookup_port<pin::pin0> 
  : std::integral_constant<int, 0> { };

template<> struct lookup_num<pin::pin0> 
  : std::integral_constant<int, 520> { };

template<> struct lookup_port<pin::pin1> 
  : std::integral_constant<int, 22> { };

template<> struct lookup_num<pin::pin1> 
  : std::integral_constant<int, 5440> { };

int main()
{
    static_assert(lookup_port<pin::pin0>::value == 0, "");
    static_assert(lookup_port<pin::pin1>::value == 22, "");

    static_assert(lookup_num<pin::pin0>::value == 520, "");
    static_assert(lookup_num<pin::pin1>::value == 5440, "");
}

在C ++ 14中,由于 switch 函数可以是constexpr.rel ="noreferrer">放松的constexpr限制.

In C++14, your switch function could be constexpr, thanks to relaxed constexpr restrictions.

这篇关于枚举的编译时查找表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆