lumol-org / soa-derive

Array of Struct to Struct of Array helpers in Rust
Apache License 2.0
396 stars 28 forks source link

Generics programming using soa-derive #66

Open Alexandre425 opened 1 month ago

Alexandre425 commented 1 month ago

Hi, apologies for not being able to infer this from the documentation and code, I am not very experienced with these topics. Also, sorry if I get any terms wrong, either way, my question is the following:

Say I have a generic struct that is meant to include various types of SoAs. What trait bounds am I meant to use? Should T be a Cheese or a CheeseVec?

pub struct SparseSet<T: ?> {
    dense: Vec<EntID>,
    sparse: Vec<u32>,
    data: ?,
}

From my understanding of the documentation, you are meant to apply the trait bound StructOfArray, making T a CheeseVec. However, that trait does not implement the usual methods (insert, pop, etc.), which would mean I can't do generic implementations. Is that the case, or did I miss something?

If T is a SoA, how do I get the original type, for declaring function parameter types? For example, the function get makes use of the sparse array to determine if an entity exists, after which it's meant to return the associated data, in this case a Cheese. What should ? be here, i.e. how do I get Cheese from CheeseVec in a generic way?

/// Gets the data associated with the entity from the set
pub fn get(&self, ent_id: EntID) -> Result<&?, Error> {
    self.ent_exists(ent_id)
        .then(|| &self.data[self.sparse[ent_id] as usize])
        .ok_or(Error::EntityNotInSet)
}

Thank you.

Alexandre425 commented 1 month ago

I made some progress in realizing the type refers to the derived CheeseVec, and so my implementation now looks like this:

pub struct SparseSet<T: StructOfArray> {
    dense: Vec<EntID>,
    sparse: Vec<u32>,
    data: <T as StructOfArray>::Type,
}

However, this still will not allow me to have generic implementations, as the following errors:

pub fn new() -> Self {
    Self {
        dense: Vec::new(),
        sparse: Vec::new(),
        data: <T as StructOfArray>::Type::new(),
    }
}

error[E0599]: no function or associated item named new found for associated type <T as StructOfArray>::Type in the current scope

Do I have any alternatives? Any trait that implements the methods I need, so that I can have generic implementations?

Luthaf commented 1 month ago

Hey! I never used this code in a generic context, so I'm not sure if there is a workaround for the lack of associated methods.

StructOfArray::Type was added by @mikialex who wanted to do something similar in #24/#25. Maybe they have more idea about how to achieve this?

Alexandre425 commented 1 month ago

I see, I did find that PR, that commit was what helped me figure out part of it. If @mikialex can let me know if they've ever done generic implementations using their contribution, that would be really helpful. Otherwise I suppose I will look for an alternative, macros perhaps.