Вы можете добавить уровень косвенности. Сначала введите тег:
template<class T, std::uint8_t v> struct Tag {
using Type = T;
static constexpr std::uint8_t value = v;
};
А затем напишите:
template<class... Tags>
void func() { /* ... */ }
func<Tag<Type1, 0x03>, Tag<Type2, 0x3C>, Tag<Type3, 0xC0>>();
Вы можете извлечь T
и v
через членов Type
и value
. Например:
template<class... Tags>
void func() {
std::tuple<typename Tags::Type...> tuple;
std::uint8_t values[] = {Tags::value...};
}
Изменить. Если я правильно получил ваше обобщение, вы можете захотеть что-то вроде этого:
template<class... Tags>
std::tuple<typename Tags::Type...> unpack_from_single_byte(std::uint8_t value) {
return std::tuple<typename Tags::Type...>{
static_cast<typename Tags::Type>(Tags::value & value)...};
}
... = unpack_from_single_byte<
Tag<Type1, 0x03>, Tag<Type2, 0x3C>, Tag<Type3, 0xC0>>(0x20);
Эта функция возвращает std::tuple
(обобщение Unpacked
) с каждым членом, равным Tag::value & value
, где value
- параметр функции.
Альтернативный синтаксис без Tag
s может быть:
template<class... Enums, typename... Bitmasks>
std::tuple<Enums...> unpack_from_single_byte(std::uint8_t value, Bitmasks... bitmasks) {
static_assert(sizeof...(Enums) == sizeof...(Bitmasks));
return std::tuple<Enums...>{static_cast<Enums>(value & bitmasks)...};
}
... = unpack_from_single_byte<Type1, Type2, Type3>(0x20, 0x03, 0x3C, 0xC0);