C++ 取决于静态参数包字段的返回类型

C++ 取决于静态参数包字段的返回类型,c++,entity-framework,c++11,tuples,C++,Entity Framework,C++11,Tuples,我最近一直在试验参数包,因为它们似乎满足了我开发中的一个相当大的需求。然而,我遇到了一个问题,对于这个问题,参数包似乎是一个可行的解决方案,但我无法解决这个特殊问题。目前的问题是如何获取参数包中的每个类型,从该类型的静态字段中检索第n个元素,并在元组中返回该元素(以及其他元素)。如果措辞有点不清楚,我当前的用例如下: PictureComponent::elements = [(picture: "somePic.jpg", id: 1), (picture: "otherPic.jpg", i

我最近一直在试验参数包,因为它们似乎满足了我开发中的一个相当大的需求。然而,我遇到了一个问题,对于这个问题,参数包似乎是一个可行的解决方案,但我无法解决这个特殊问题。目前的问题是如何获取参数包中的每个类型,从该类型的静态字段中检索第n个元素,并在元组中返回该元素(以及其他元素)。如果措辞有点不清楚,我当前的用例如下:

PictureComponent::elements = [(picture: "somePic.jpg", id: 1), (picture: "otherPic.jpg", id: 2)]
PositionComponent::elements = [(pos: (1,2), id: 2), (pos: (4,5), id: 3)]
/*警告:可能是不必要的细节*/

我的程序的架构是一个。本质上,有多个系统定义程序不同区域的逻辑。这些系统作用于实体,实体由多个组件(包含特定数据段,例如DescriptionComponent)组成。每个系统将验证给定实体是否具有所有必需的组件,然后执行特定于系统的逻辑

为了实现这一点,我创建了一个组件基类,从中派生特定的组件。每个派生组件都包含一个静态向量,该向量充当该类型所有组件的管理器。每个组件都有一个entityId字段,该字段引用其所属实体,静态向量根据该id排序

目前,在给定的系统中,我可以通过查看系统所需的组件,然后找到所有包含相同entityId的组件集,并对这些组件执行逻辑,来找到适用的实体。然而,我正在做的逻辑是在这一点上手动迭代组件的静态向量,因为每个系统在组件类型方面都有不同的需求

举个简单的例子,以防上面的内容不清楚:

假设DisplaySystem需要PictureComponent和PositionComponent。现在,假设管理这些类型的静态字段如下所示:

PictureComponent::elements = [(picture: "somePic.jpg", id: 1), (picture: "otherPic.jpg", id: 2)]
PositionComponent::elements = [(pos: (1,2), id: 2), (pos: (4,5), id: 3)]
目前,每个组件都有自己的迭代器。从零开始,我们用最低的entityId增加组件索引(因为向量是按此键排序的)。在上面的示例中,我们将尝试索引(0,0),请参见id 1小于id 2,因此请使用第一个索引。然后我们尝试(1,0),看到两个组件都有EntityID2,并将它们作为一对传递给系统以执行逻辑。然后我们将碰撞两个索引,尝试(2,1),并超出PictureComponent向量的边界,然后完成

/*结束免费细节*/

对于这个问题,我设想的解决方案是一个模板化的参数包类,它接受所需的组件类型,并输出EntityID都匹配的组件元组。这方面的伪代码如下

template <typename... RequiredComponentTypes>
class ComponentIterator {
   /* standard input iterator functionality*/
   ...

   array componentIndices // same size as our param pack, one index per type

   tuple<RequiredComponentTypes...> getNextSetOfComponents() {
      while every component's entity id is not equal:
         find the currently indexed component with the lowest entity id;
         increment the current index of that component type;

      out of the while, once we have a set of components with the same entity id:
         return a tuple of the indexed components for each type. **//this is the part I have no idea how to do**
   }
}
模板
类组件迭代器{
/*标准输入迭代器功能*/
...
数组组件//与参数包大小相同,每种类型一个索引
元组GetNextSetTofComponents(){
虽然每个组件的实体id不相等:
查找实体id最低的当前索引组件;
增加该组件类型的当前索引;
此外,一旦我们拥有一组具有相同实体id的组件:
返回每种类型的索引组件的元组。**//这是我不知道如何做的部分**
}
}
正如代码中所指出的,将其值从索引检索到类型的静态字段的元组返回过程是我不确定的部分。对于任何数量的模板参数,手动操作都很简单(如果我有一组命名的参数化类型,那么创建元组就像使用适当的值调用make_tuple一样简单。)但是,在处理参数包时,我不确定如何绕过这个问题


如果您能提供任何帮助,我们将不胜感激。如果您需要任何澄清或更多细节,请随时通知我。谢谢

您可以执行以下操作:

template <typename... Ts>
class ComponentIterator {
    static constexpr std::size_t size = sizeof...(Ts);

public:
    ComponentIterator() : indices(), finished(false) { adjust(); }

    std::tuple<Ts&...> get()
    {
        return get(std::index_sequence_for<Ts...>());
    }

    ComponentIterator& operator ++()
    {
        for (auto& e : indices) {
            ++e;
        }
        adjust();
        return *this;
    }

    bool is_finished() const { return finished; }
private:
    void adjust()
    {
        adjust(std::index_sequence_for<Ts...>());
    }

    template <std::size_t...Is>
    std::tuple<Ts&...> get(std::index_sequence<Is...>)
    {
        return std::tie(Ts::elements[indices[Is]]...);
    }

    template <std::size_t...Is>
    void adjust(std::index_sequence<Is...>) {
        bool is_ended[size] = {indices[Is] == Ts::elements.size()...};
        if (std::any_of(std::begin(is_ended), std::end(is_ended),
            [](bool b) { return b; })) {
            finished = true;
            return;
        }

        int min_value = std::min({Ts::elements[indices[Is]].id...}) - 1;
        for (;;)
        {
            ++min_value;
            bool increases[size] = {increase_until<Ts>(indices[Is], min_value)...};
            if (std::any_of(std::begin(increases), std::end(increases),
                [](bool b) { return !b; })) {
                finished = true;
                return;
            }
            const int ids[size] = {Ts::elements[indices[Is]].id...};
            if (std::all_of(std::begin(ids), std::end(ids),
                [min_value](int id) { return id == min_value;})) {
                return;
            }
        }
    }

    template <typename T>
    bool increase_until(std::size_t& index, int min_value)
    {
        for (; index != T::elements.size(); ++index) {
            if (min_value <= T::elements[index].id) {
                return true;
            }
        }
        return false;
    }
private:
    std::array<std::size_t, size> indices;
    bool finished;
};
模板
类组件迭代器{
静态constexpr std::size\u t size=sizeof…(Ts);
公众:
ComponentIterator():index(),finished(false){adjust();}
std::tuple get()
{
返回get(std::index_sequence_for());
}
组件迭代器和运算符++()
{
用于(自动和电气:索引){
++e;
}
调整();
归还*这个;
}
bool is_finished()常量{return finished;}
私人:
无效调整()
{
调整(std::index_sequence_for());
}
样板
std::tuple get(std::index\u序列)
{
返回std::tie(Ts::elements[index[Is]]…);
}
样板
无效调整(标准::索引顺序){
bool是结束的[size]={index[is]==Ts::elements.size()…};
如果(std::begin(已结束)、std::end(已结束)中的任何一个,
[](bool b){return b;}){
完成=正确;
回来
}
int min_value=std::min({Ts::elements[index[Is]]].id..})-1;
对于(;;)
{
++最小值;
bool增加[size]={增加[u直到(索引[Is],最小值)…};
如果(std::开始(增加)、std::结束(增加)中的任何值,
[](bool b){return!b;}){
完成=正确;
回来
}
const int id[size]={Ts::elements[index[Is]]].id.};
如果(std::所有(std::开始(ids),std::结束(ids),
[min_值](int-id{return-id==min_值;})){
回来
}
}
}
样板
bool增加直到(标准::大小和索引,整数最小值)
{
对于(;index!=T::elements.size();++index){

如果(min_值)这个操作非常有效,那么std::integer_序列似乎是对C++14的一个很好的补充。谢谢你的提示!