过滤嵌套动态元组(dynamic tuple of tuples)
Filtering nested dynamic tuple (dynamic tuple of tuples)
我有一种动态元组结构:
template <typename... Elems> //Should only be tuples
class DynamicTuple {
vector<byte> data; //All data is stored contiguously
vector<tuple<size_t,size_t>> element_table; //First element is offset into the data vector; second is which index of the parameter pack holds the stored type.
/* ... */
}
现在我希望能够过滤掉所有包含类型列表的元组。
template <typename... Ts>
vector<tuple<Ts&...>> filter() {
vector<tuple<Ts&...>> result;
for (auto it : element_table) {
auto [offset, type] = it;
// ???
}
}
这里我需要能够检查"Elems"参数包的第N个索引中的类型是否是包含"Ts"参数包中所有类型的元组。如果是这样,我想推回一个包含这些值的元组。
直觉上我想使用 "type" 值从 "Elems" 参数包中获取类型,并使用 has_type 结构,就像这个答案中的结构: 类似于:
((has_type<Ts, tuple_element<type, tuple<Elems...>>::type>&& ...))
但是这不起作用,因为 "type" 不是编译时常量表达式。
有办法解决这个问题吗?
但是这不起作用,因为 "type" 不是编译时常量表达式。有办法解决这个问题吗?
不可能return基于运行时值的不同类型。
您要么必须求助于可以在运行时评估的东西(例如使用 vector
) 或 有 输入 是编译时间常数。
运行时解决方案可以使用 type_id
或类似的解决方案。
有了你已有的has_type
,你可以用同样的方式定义一个type_subset
来测试元组中是否包含所有类型:
template <typename Ts, typename Tuple>
struct type_subset;
template <typename... Ts, typename... Us>
struct type_subset<std::tuple<Ts...>, std::tuple<Us...>>
: std::conjunction<has_type<Ts, std::tuple<Us...>>...> {};
然后您可能想通过遍历参数包和相应的索引来找到与您的 type
索引匹配的正确类型:
size_t i = 0;
bool match = ((type == i++ && type_subset<std::tuple<Ts...>, Elems>::value) || ...);
确保在每次执行折叠表达式之前将 i
重置为 0
。您可能希望将整个内容放在 lambda 或函数中以分隔 i
并在其他条件下重用它。
也许更好的做法是在编译时将可能的结果保存到一个数组中,然后在运行时对其进行索引:
constexpr static std::array matches{type_subset<std::tuple<Ts...>, Elems>::value...};
bool match = matches[type];
无论哪种情况,您都需要确保 type < sizeof...(Elems)
。特别是在第二个变体中,否则你将有未定义的行为(如果你不使用 .at
而不是 []
)。
我有一种动态元组结构:
template <typename... Elems> //Should only be tuples
class DynamicTuple {
vector<byte> data; //All data is stored contiguously
vector<tuple<size_t,size_t>> element_table; //First element is offset into the data vector; second is which index of the parameter pack holds the stored type.
/* ... */
}
现在我希望能够过滤掉所有包含类型列表的元组。
template <typename... Ts>
vector<tuple<Ts&...>> filter() {
vector<tuple<Ts&...>> result;
for (auto it : element_table) {
auto [offset, type] = it;
// ???
}
}
这里我需要能够检查"Elems"参数包的第N个索引中的类型是否是包含"Ts"参数包中所有类型的元组。如果是这样,我想推回一个包含这些值的元组。
直觉上我想使用 "type" 值从 "Elems" 参数包中获取类型,并使用 has_type 结构,就像这个答案中的结构: 类似于:
((has_type<Ts, tuple_element<type, tuple<Elems...>>::type>&& ...))
但是这不起作用,因为 "type" 不是编译时常量表达式。 有办法解决这个问题吗?
但是这不起作用,因为 "type" 不是编译时常量表达式。有办法解决这个问题吗?
不可能return基于运行时值的不同类型。
您要么必须求助于可以在运行时评估的东西(例如使用 vector
) 或 有 输入 是编译时间常数。
运行时解决方案可以使用 type_id
或类似的解决方案。
有了你已有的has_type
,你可以用同样的方式定义一个type_subset
来测试元组中是否包含所有类型:
template <typename Ts, typename Tuple>
struct type_subset;
template <typename... Ts, typename... Us>
struct type_subset<std::tuple<Ts...>, std::tuple<Us...>>
: std::conjunction<has_type<Ts, std::tuple<Us...>>...> {};
然后您可能想通过遍历参数包和相应的索引来找到与您的 type
索引匹配的正确类型:
size_t i = 0;
bool match = ((type == i++ && type_subset<std::tuple<Ts...>, Elems>::value) || ...);
确保在每次执行折叠表达式之前将 i
重置为 0
。您可能希望将整个内容放在 lambda 或函数中以分隔 i
并在其他条件下重用它。
也许更好的做法是在编译时将可能的结果保存到一个数组中,然后在运行时对其进行索引:
constexpr static std::array matches{type_subset<std::tuple<Ts...>, Elems>::value...};
bool match = matches[type];
无论哪种情况,您都需要确保 type < sizeof...(Elems)
。特别是在第二个变体中,否则你将有未定义的行为(如果你不使用 .at
而不是 []
)。