I've recently been experimenting with parameter packs, since they seem to fill a pretty big need in my development. However, I've been running up against a problem for which parameter packs seem to be a feasible solution, but I can't figure out this particular issue. The issue at hand is how to take each type in the parameter pack, retrieve the n-th element from a static field in that type, and return that element (along with the others) in a tuple. In case that wording was a bit unclear, my current use-case is as follows:
/* WARNING: Possibly gratuitous detail */
The architecture of my program is that of an Entity-Component System. Essentially, there are multiple systems that define the logic of different areas of the program. These systems act on entities, which are composed of multiple components (which contain a specific piece of data, e.g. DescriptionComponent). Each system will verify that a given entity has all required components, then perform the system-specific logic.
To accomplish this, I have created a component base class from which specific components are derived. Each derived component contains a static vector which acts as a manager for all components of that type. Each component has an entityId field which references its owning entity, and the static vector is sorted on this id.
Currently, in a given system, I am able to find applicable entities by looking at the components which the system requires, then finding the sets of components which all contain the same entityId and performing the logic on those components. However, I am doing the logic to iterate through the static vectors of the components manually at this point, since each system will have different requirements in terms of component types.
A quick example, just in case the above wasn't clear:
Say DisplaySystem requires a PictureComponent and a PositionComponent. Now say the static fields managing these types are as follows:
PictureComponent::elements = [(picture: "somePic.jpg", id: 1), (picture: "otherPic.jpg", id: 2)]
PositionComponent::elements = [(pos: (1,2), id: 2), (pos: (4,5), id: 3)]
Currently, each component has its own iterator. Starting at zero, we bump up the component index with the lowest entityId (since the vectors are sorted on this key). In the above example, we'd try indices (0,0), see the id 1 is less than id 2, so bump the first index. Then we'd try (1,0), see that both components have entityId 2, and pass those to the system as a pair to perform logic on. Then we'd bump both indices, try (2,1), and be out of the bounds of the PictureComponent vector, and be done.
/* END Gratuitous detail */
The solution that I'd imagine for this problem would be a single templated parameter pack class which takes in the required component types and outputs tuples of components whose entityIds all match. The pseudo-code for this would be as follows
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**
}
}
As noted in the code, the process of returning a tuple whose values are retrieved from an index to the static field on the types is the part I'm unsure about. For any number of template parameters, it's trivial to do manually (if I have a set of named parameterized types, then making the tuple is as simple as calling make_tuple with the appropriate values.) However, when dealing with a parameter pack, I'm not sure how to get around the issue.
Any help you all could offer would be greatly appreciated, and if you need any clarification or more details, please don't hesitate to let me know. Thanks!
Aucun commentaire:
Enregistrer un commentaire