mardi 27 octobre 2015

Compile-time lookup table for enum

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;
    }
}

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).

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 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).

Aucun commentaire:

Enregistrer un commentaire