【问题标题】:How can I select a subset of tuple types and create another tuple from contents of the subset?如何选择元组类型的子集并从子集的内容创建另一个元组?
【发布时间】:2021-08-09 23:17:06
【问题描述】:

我有一个使用可变参数定义的结构元组:

#include <tuple>
#include <vector>

template<class Type>
struct Pool {
  std::vector<Type> components;
};

template<class... Types>
class Storage {
public:
  std::tuple<Pool<Types>...> pools;

  template<class SelectedType0, class... SelectedTypes>
  std::tuple<std::vector<SelectedTypes>&...> getVectorsFromTuple();

  template<class... SelectedTypes>
  void iterate();
};

我想要一种从元组中选择类型子集并基于其内容创建新元组的方法。本质上,这就是我想要实现的目标:

template<class... Types>
template<class... SelectedTypes>
void Storage<Types...>::iterate() {
  std::tuple<std::vector<SelectedTypes>&...> vectors = getVectorsFromTuple<SelectedTypes...>(pools);
  // getVectorsFromTuple should get the values in the tuple based on types
  // and save reference to each tuple item's structure's `components`
  // property in another tuple 
}

我得到的一个想法是在另一个函数中“定义”第一个模板参数,然后使用该函数递归地定义其他参数:

template <class... Types>
template<class SelectedType0, class... SelectedTypes>
inline std::tuple<std::vector<SelectedType0>&, std::vector<SelectedTypes>&...> EntityStorageSparseSet<ComponentTypes...>::getVectorsFromPools() {
    return std::make_tuple(std::get<PickComponent0>(pools).components, getVectorsFromPools<PickComponents...>());
}

但我不知道如何展开/展平递归元组,所以此函数返回如下内容:

std::tuple<SelectedType0, SelectedType1, ...>

而不是

std::tuple<SelectedType0, std::tuple<SelectedType1, std::tuple<SelectedType2, ...>>>

如何展开元组或有更好的方法来实现我想要实现的目标?

【问题讨论】:

  • 第一个模板声明不编译。你能显示一个真实的minimal reproducible example吗?
  • 更新了所有的sn-ps,现在编译:ideone.com/w96TBc
  • 我注意到您在上一个问题中说您可以使用模板递归地执行此操作,但希望使用折叠来执行此操作。如果我理解正确,您可以展示有效的递归解决方案,也许有人可以将其变成折叠表达式。
  • 好的,现在图片更清晰了,都是Types 唯一的,或者它们可以不是唯一的,如果是这样,选择语义如何工作,正因为如此。真的,如果它们不是唯一的,std::get 在银盘上为您提供元组中的给定类型;所以这对我来说似乎相当简单,核心。
  • 如果你改用std::get&lt;Pool&lt;Types&gt;&gt;(pools).componentsSam Varshavchik's solution 不工作吗?

标签: c++ c++17 variadic-templates template-meta-programming


【解决方案1】:

以下似乎可以完成工作(假设 Types 中的类型是唯一的):

template <typename... Types>
template <typename... SelectedTypes>
std::tuple<std::vector<SelectedTypes>&...>
EntityStorageSparseSet<Types...>::getVectorsFromPools()
{
    return { std::get<SelectedTypes>(pools).components... };
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2017-07-11
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 2017-07-23
    • 1970-01-01
    相关资源
    最近更新 更多