Reputation: 67
I'm working on some low level drivers and I thought I'd use C++ templates to spice it up.
In Verilog, you can define bitmasks using [h:l]
notation where h
is the high bit, l
is the low bit. I have a data structure already defined for this:
uint16_t mask(uint8_t h, uint8_t l) {
return h << 8 + l;
}
I'd like to memoize these bitmasks. Say I want to modify bits [7:4] of register R, if I've already read in R before hand I can just modify the old value of R before writing it, rather than sending out a new read request to my device.
To find the number of bytes needed for each memoization, I already have a function
constexpr uint8_t requiredBytes(uint16_t mask)
which returns the number of bytes needed to hold the mask.
Is there a way to static-time declare a memoization buffer for ease of analysis? (this will run on embedded platforms)
I assume I need a pipeline like below:
template <uint16_t... masks>
(1) V
Apply requiredBytes() to each mask in the template
(2) V
Convert each value from requirdBytes to a type (requiredBytes() = 1 => uint8_t, ...)
(3) V
Convert this list of types into a std::tuple<>
I know I can do transformation 2 using a series of template specializations, which leads to my question, how can we implement transformations 1 and 3?
Upvotes: 1
Views: 70
Reputation: 118300
I presume that your step 2, which you've described as already a done deal, is something along the lines of
typename bytesType<n>::type
Where the template parameter n
is the number of bytes, and this gives you the type via an appropriate specialization. If so, then this seems to be something along the lines of a straightforward pack expansion:
template <uint16_t ...masks>
using tuple_mask=std::tuple<typename bytesType<requiredBytes(masks)>::type...>;
requiredBytes()
is a constexpr, this provides the parameter to bytesType
, which gives you the type. Then, pack-expand it, and feed it into a std::tuple
declaration.
Upvotes: 1