【问题标题】:Filtering nested dynamic tuple (dynamic tuple of tuples)过滤嵌套动态元组(动态元组的元组)
【发布时间】:2019-12-16 08:02:05
【问题描述】:

我有一种动态元组结构:

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 结构:https://stackoverflow.com/a/41171291/11463887 类似:

((has_type<Ts, tuple_element<type, tuple<Elems...>>::type>&& ...))

但这不起作用,因为“type”不是编译时常量表达式。 有没有办法解决这个问题?

【问题讨论】:

  • decltype(type)?
  • @walnut 这将阻止它变得动态。我明白这就是为什么我的方式,使用 tuple_element 行不通的原因——我要求的是一种在运行时执行此操作的方法。
  • @walnut 我的意思是动态的,就像 std::vector 是动态的,而 std::array 不是。我在运行时将各种类型存储在数据向量中,并且需要 element_table 来查找存储在其中的类型。如果我推回数据向量中的浮点数,我还需要推回 { data.end(0), Index::value } (取自stackoverflow.com/a/26169248/11463887),所以 element_table 存储DynamicTuple 持有的每个元组都有一个元素。

标签: c++ templates tuples variadic-templates


【解决方案1】:

使用您已经拥有的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 &lt; sizeof...(Elems)。特别是在第二个变体中,否则您将有未定义的行为(如果您不使用 .at 而不是 [])。

【讨论】:

  • 这完全是我想要的,但现在我正在尝试实现它,特别是使用 constexpr 版本,我很难让它工作。 Matches 的长度始终为 1。可能是因为我将 type_subset&lt;std::tuple&lt;Ts...&gt;, Elems&gt;::value, ... 包裹在括号中,否则无法编译。
  • @meatandmahjong 抱歉,我使用了错误的语法。逗号不应该在那里并且缺少分号,请参阅更新的问题。如果将其括在括号中,它将具有不同的含义(带有逗号运算符的折叠表达式)。
【解决方案2】:

但这不起作用,因为“type”不是编译时常量表达式。有没有办法解决这个问题?

不可能根据运行时值返回不同的类型。

您要么必须求助于可以在运行时评估的东西(例如使用vector要么输入成为编译时间常数。

运行时解决方案可以使用 type_id 或类似的。

【讨论】:

  • "type" 是 element_table 中的 size_t 值。我不必根据值返回不同的类型。例如,我可以让它返回一个 vector> 并在元组不包含该类型时返回一个 nullptr。但主要问题是如何弄清楚 Elems 参数包中的每个元组如何包含 Ts 参数包中的每个类型
猜你喜欢
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 2023-02-18
  • 2019-07-09
相关资源
最近更新 更多