Соедините не тип с каждым типом в шаблонах variadi c - PullRequest
0 голосов
/ 19 апреля 2020

Есть ли какой-нибудь способ, которым я могу иметь пару типов c? Моя цель - добавить дополнительную информацию с каждым типом.

Примерно так:

// non compilable code

// I want to pass an extra uint8_t with each type here.
template<template<typename EnumType, uint8_t Bitmask> typename... EnumsAndBitmasks>
void func(){
    // Unpack EnumsAndBitmasks and do something with pairs of each EnumType and it's Bitmask
}

// Call func like this
enum class Type1 : uint8_t;
enum class Type2 : uint8_t;
enum class Type3 : uint8_t;

func<<Type1,0x03>, <Type2,0x3C>, <Type3,0xC0>>();

Ниже приведен не шаблонный рабочий код, но я хочу обобщить этот процесс, предоставив возвращаемую структуру введите каждый EnumType и его битовую маску в качестве аргумента шаблона для функции unpack_from_single_byte.

enum class EnumType1 : uint8_t { first, second };
enum class EnumType2 : uint8_t { first, second, third, forth };
enum class EnumType3 : uint8_t { first, second };

struct Unpacked
{
    EnumType1 var1;
    EnumType2 var2;
    EnumType3 var3;
};

Unpacked unpack_from_single_byte(uint8_t value)
{
        return { static_cast<EnumType1>(value & 0x01), 
                 static_cast<EnumType2>(value & 0x06), 
                 static_cast<EnumType3>(value & 0x0F) };
}

1 Ответ

1 голос
/ 19 апреля 2020

Вы можете добавить уровень косвенности. Сначала введите тег:

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