Alternative to dynamic creation of variable names

2

I have a header file (not written by me, which I cannot change) which contains definitions in the following format:

#define     SPC_TMASK0_NONE         0x00000000
#define     SPC_TMASK0_CH0          0x00000001
#define     SPC_TMASK0_CH1          0x00000002
#define     SPC_TMASK0_CH2          0x00000004
#define     SPC_TMASK0_CH3          0x00000008
#define     SPC_TMASK0_CH4          0x00000010
#define     SPC_TMASK0_CH5          0x00000020
#define     SPC_TMASK0_CH6          0x00000040
#define     SPC_TMASK0_CH7          0x00000080
#define     SPC_TMASK0_CH8          0x00000100
#define     SPC_TMASK0_CH9          0x00000200
#define     SPC_TMASK0_CH10         0x00000400
#define     SPC_TMASK0_CH11         0x00000800
#define     SPC_TMASK0_CH12         0x00001000
#define     SPC_TMASK0_CH13         0x00002000
#define     SPC_TMASK0_CH14         0x00004000
#define     SPC_TMASK0_CH15         0x00008000
#define     SPC_TMASK0_CH16         0x00010000
#define     SPC_TMASK0_CH17         0x00020000
#define     SPC_TMASK0_CH18         0x00040000
#define     SPC_TMASK0_CH19         0x00080000
#define     SPC_TMASK0_CH20         0x00100000
#define     SPC_TMASK0_CH21         0x00200000
#define     SPC_TMASK0_CH22         0x00400000
#define     SPC_TMASK0_CH23         0x00800000
#define     SPC_TMASK0_CH24         0x01000000
#define     SPC_TMASK0_CH25         0x02000000
#define     SPC_TMASK0_CH26         0x04000000
#define     SPC_TMASK0_CH27         0x08000000
#define     SPC_TMASK0_CH28         0x10000000
#define     SPC_TMASK0_CH29         0x20000000
#define     SPC_TMASK0_CH30         0x40000000
#define     SPC_TMASK0_CH31         0x80000000

I have a function which is accepts a channel number (0-31) and I want to find the corresponding macro expansion (SPC_TMASK0_NONE, SPC_TMASK0_CH0... etc).

I thought that creating the macro expansion dynamically (as a string) would be the easiest/neatest/cleanest but it seems that I can't do that so can someone suggest a better alternative to go from channel number to macro expansion?

I know that the number corresponding to the macro expansion could be used directly, but this has the potential to change so I need to use the names to ensure correct operation over time.

I really don't want a big if else / switch case - I was thinking of an array with the names in and the channel number is used to select the element but that felt clunky as well.

c++
asked on Stack Overflow Jan 8, 2019 by Tim Mottram • edited Jan 9, 2019 by Tim Mottram

1 Answer

5

If you need to map a runtime integer to a macro's value, your best bet is indeed an array. But you don't have to write it yourself!

#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/cat.hpp>

constexpr auto channelMask(int channelNumber) {
    constexpr std::uint32_t array[] {
#define detail_channelMask_case(z, n, data) \
    BOOST_PP_CAT(SPC_TMASK0_CH, n),

    BOOST_PP_REPEAT(32, detail_channelMask_case, ~)

#undef detail_channelMask_case
    };

    return array[channelNumber];
}

This generates the array with the macros 0 to 31, and indexes into it. I leave it to you to handle input limits and the SPC_TMASK0_NONE macro :)

answered on Stack Overflow Jan 8, 2019 by Quentin

User contributions licensed under CC BY-SA 3.0