将非类型与可变参数模板中的每种类型配对
Pair a non-type with each type in variadic templates
有什么方法可以让我拥有可变类型对?我的目标是为每种类型添加额外的信息。
大概是这样:
// 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) };
}
您可以添加一个间接级别。首先介绍一个标签:
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>>();
可以通过成员Type
和value
提取T
和v
。例如:
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);
这个函数returns一个std::tuple
(Unpacked
的泛化),每个成员等于Tag::value & value
,其中value
是函数参数。
没有 Tag
的替代语法可能是:
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);
有什么方法可以让我拥有可变类型对?我的目标是为每种类型添加额外的信息。
大概是这样:
// 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) };
}
您可以添加一个间接级别。首先介绍一个标签:
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>>();
可以通过成员Type
和value
提取T
和v
。例如:
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);
这个函数returns一个std::tuple
(Unpacked
的泛化),每个成员等于Tag::value & value
,其中value
是函数参数。
没有 Tag
的替代语法可能是:
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);